CTYPES和PYTHON3:无法返回长字符串 [英] CTYPES and PYTHON3: Can't return long string
问题描述
我有一个C ++代码,为此我创建了一个python.ctypes包装器。它工作得很好,除非返回的字符串很长。 C代码示例:
I have a C++ code for which I created a python.ctypes wrapper. It works quite well, except when the returning string is long. Example of C code:
extern "C" {
const char * hallo(char * nome)
{
string str(nome);
str = "hallo " + str;
for(int i=0; i<100; i++)
str += " new content";
return str.c_str();
}
我的python代码是:
My python code is:
self.lib = ctypes.CDLL(LIB_PATH)
self.lib.hallo.restype = ctypes.c_char_p
self.lib.hallo.argtypes =[ctypes.c_char_p]
j = self.lib.hallo('my name'.encode())
print('INIT: ' + j.decode())
字符串大小是动态的(实际上,它将是一个json字符串)。解决这种情况的最佳方法是什么?
The string size is dynamic (in fact, it will be a json string). What is the best way to deal with this situation?
非常感谢。
推荐答案
这里的问题是,当您返回str.c_str()
时,您将返回指向堆栈分配内存的指针,该指针在从C ++代码返回时将被覆盖。
The issue here is that when you return str.c_str()
you're returning a pointer to stack allocated memory which gets overwritten on return from the C++ code.
可能的解决方法是使用静态字符串str
,例如:
Potential workarounds are to use static string str
such as:
#include <string>
#include <sstream>
extern "C" {
const char * hallo(char * nome)
{
static std::string str;
std::stringstream stream;
stream << "hallo " << nome;
for(int i=0; i<100; i++)
stream << " new content";
str = stream.str();
return str.c_str();
}
}
尽管这样做会阻止您打电话
Although this will prevent you from calling the routine from multiple threads.
如果希望能够从多个位置调用该例程,则可能应该将参数指针指向某个内存,然后传递一个指针由 ctypes.create_string_buffer
创建的缓冲区(希望在这种情况下具有合适的大小)。
If you want to be able to call it from multiple places, you should probably take a parameter pointer to some memory, and pass in a pointer buffer created from ctypes.create_string_buffer
(hoping that it has the right size in this case).
例如:
#include <string>
#include <sstream>
extern "C" {
const char * hallo(char * nome, char *writebuffer, unsigned int buffersize)
{
std::string str(nome);
str = "hallo " + str;
for(int i=0; i<100; i++)
str += " new content";
if (str.size() < buffersize) {
str.copy(writebuffer, buffersize);
return writebuffer;
} else {
return 0;
}
}
}
然后一些使用该库的示例python代码;传入128k缓冲区(已更新python 3):
Then some sample python code that uses this library; passing in a 128k buffer (python 3 updated):
import ctypes
lib = ctypes.CDLL(LIB_PATH)
lib.hallo.restype = ctypes.c_char_p
lib.hallo.argtypes =[ctypes.c_char_p, ctypes.c_char_p, ctypes.c_uint]
allocation = ctypes.create_string_buffer(128 * 1024)
j = lib.hallo('my name'.encode(), allocation, 128 * 1024)
if j is not None:
print('INIT: ' + j.decode("UTF-8"))
else:
print("Buffer was too small")
这篇关于CTYPES和PYTHON3:无法返回长字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!