首页 > 解决方案 > 如何使用 malloc 将 char** 返回到 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;
}

当我尝试names在 Python中打印出ValueError: NULL pointer access.

正如我所说,我有这样的作品。在 Python 中,如果我不使用POINTER(c_char_p)但指定一些指针,例如c_char_p*4096malloc从 C 代码中删除,我可以得到很好的结果。不过,理想情况下,我想在 C 端分配内存。我觉得我缺少一些微妙之处。

我正在使用 Python 3.5.2,以防万一。

标签: pythoncctypes

解决方案


该声明:

names = (char**) malloc(sizeof(char*) * count);

分配内存,names但 Python 中的调用者不会看到这个。为此,请使用:

*names = (char**) malloc(sizeof(char*) * count);

这意味着您必须将函数声明为:

int getStrings(char* fname, char ***names)

三重间接。

我不知道你需要在 Python 中改变什么,但至少你必须传递 Pythonnames变量的地址。

正确的 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;
}

推荐阅读