我一直试图通过ctypes将char **数组返回到我的Python代码中。我有一种“工作”的方式,但是我不喜欢它,因为我必须在Python方面增加一些代码。我必须相信这是可能的。
我的Python代码:
from ctypes import *
strarray = POINTER(c_char_p)
getStr = cdll.context.getStrings
getStr.argtypes = [c_char_p, strarray]
fname = b"test.ctx"
names = strarray()
int numStrs = getStr(fname, names)
for i in range(numStrs):
print(names[i])
我的C / C ++代码:
int getStrings(char* fname, char **names)
{
int count;
int strSize;
count = getNameCount();
names = (char**) malloc(sizeof(char*) * count);
for (int i = 0; i < count; i++)
{
std::string name = getName(i);
strsize = name.length() + 1;
*names = (char*) malloc(strsize *sizeof(char));
strcpy_s(*parts, strsize, name.c_str());
*names++;
}
return count;
}
当我尝试在Python中打印出names
时,我得到了ValueError: NULL pointer access
。
正如我所说,我有类似的作品。在Python中,如果我不使用POINTER(c_char_p)
,而是指定一些类似c_char_p*4096
的指针并从C代码中删除malloc
,那么我可以得到很好的结果。不过,理想情况下,我想在C端分配内存。我觉得我缺少一些微妙之处。
以防万一,我正在使用Python 3.5.2。
答案 0 :(得分:1)
声明:
names = (char**) malloc(sizeof(char*) * count);
将内存分配给names
,但是Python中的调用者将看不到这一点。为此,请使用:
*names = (char**) malloc(sizeof(char*) * count);
这意味着您必须将函数声明为:
int getStrings(char* fname, char ***names)
三次间接访问。
我不知道您需要在Python中进行哪些更改,但是至少您必须传递Python names
变量的地址。
正确的C(C ++)代码是:
int getStrings(char* fname, char ***names)
{
int count;
int strSize;
count = getNameCount();
*names = (char**) malloc(sizeof(char*) * count);
for (int i = 0; i < count; i++)
{
std::string name = getName(i);
strsize = name.length() + 1;
(*names)[i] = (char*) malloc(strsize *sizeof(char));
strcpy_s((*names)[i], strsize, name.c_str());
}
return count;
}