我有一个C ++代码,为此我创建了python.ctypes包装器。它工作得很好,除非返回的字符串很长。C代码示例:
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();
}
Run Code Online (Sandbox Code Playgroud)
我的python代码是:
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())
Run Code Online (Sandbox Code Playgroud)
字符串大小是动态的(实际上,它将是json字符串)。处理这种情况的最佳方法是什么?
非常感谢。
这里的问题是,当您return str.c_str()返回指向堆栈分配的内存的指针时,该指针在从C ++代码返回时将被覆盖。
可能使用的解决方法static string str如下:
#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();
}
}
Run Code Online (Sandbox Code Playgroud)
尽管这将阻止您从多个线程调用例程。
如果希望能够从多个位置调用它,则可能应该将参数指针带到某些内存,并传入从其创建的指针缓冲区ctypes.create_string_buffer(在这种情况下,希望它具有正确的大小)。
例如:
#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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后是一些使用该库的示例python代码;传入128k缓冲区:
import ctypes
lib = ctypes.cdll.LoadLibrary(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: ' + allocation.value)
else:
print("Buffer was too small")
Run Code Online (Sandbox Code Playgroud)