如何使用 malloc return char** 到 ctypes

How to return char** to ctypes with malloc

我一直在尝试通过 ctypes return 一个 char** 数组到我的 Python 代码中。我有一个 "works" 的方法,但我不喜欢它,因为我必须在 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,以防万一。

声明:

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