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")
您提供的 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)