如何使用malloc将char **返回给ctypes

时间:2019-09-27 15:49:05

标签: python c ctypes

我一直试图通过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。

1 个答案:

答案 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;
}