Python中的C结构

Alc*_*ott 6 c python struct ctypes

有一个libx.so导出2功能,和struct,

typedef struct Tag {
    int num;
    char *name;
}Tag;

Tag *create(int n, char *n)
{
    Tag *t = malloc(sizeof(Tag));
    t->num = n;
    t->name = n;
    return t;
}

void use(Tag *t)
{
    printf("%d, %s\n", t->num, t->name);
}
Run Code Online (Sandbox Code Playgroud)

我想create用Python 调用然后保存Tag *res返回的create,稍后我会调用use并传递Tag *res之前保存的use,这里是它(只是为了演示):

>>>libx = ctypes.CDLL("./libx.so")
>>>res = libx.create(c_int(1), c_char_p("a"))
>>>libx.use(res)
Run Code Online (Sandbox Code Playgroud)

上面的代码可能是错误的,只是为了演示我想要做的事情.

我的问题是,我怎么能保存返回的结果create?因为它返回一个指向用户定义的指针struct,并且我不想struct Tag在Python中构造对应物,会c_void_p不会这样做?

UPDATE

从@ David的回答中,我仍然不太明白一件事:

指针(c_char_p("a"))仅在调用期间有效create.一旦create返回,那么该指针就不再有效.

当完成调用时,我分配c_char_p("a")t->namein 是一个悬空指针?因为根据引用的词,该指针不再有效.为什么不再有效?createcreatet->namecreatec_char_p("a")

Dav*_*nan 4

您提供的 C 代码根本无法工作。您需要更准确地了解哪一方分配并负责堆内存。

在当前示例中,您传递c_char_p("a")给 C 代码。但是,指向该 ctypes 内存的指针仅在调用期间有效create。一旦create返回,该指针就不再有效。但你拿了里面的指针的副本create。因此后续的调用use很可能会失败。

您将需要获取该字符串内容的副本并将其存储在结构中。如果你这样做了,那么你就可以libx.create.restype = c_void_p安全地使用。

但是,如果您希望释放分配的内存,则必须提供一个destroy与该函数匹配的函数create。经过这些更改后,C 代码将如下所示:

Tag *create(int n, char *s)
{
    Tag *t = malloc(sizeof(Tag));
    t->num = n;
    t->name = strdup(s);
    return t;
}

void destroy(Tag *t)
{
    free(t->name);
    free(t);
}
Run Code Online (Sandbox Code Playgroud)

Python 代码如下所示:

libx = ctypes.CDLL("./libx.so")
libx.create.restype = c_void_p
res = libx.create(c_int(1), c_char_p("a"))
libx.use(res)
libx.destroy(res)
Run Code Online (Sandbox Code Playgroud)