python - Python 中的 C 结构

标签 python c 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);
}

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

>>>libx = ctypes.CDLL("./libx.so")
>>>res = libx.create(c_int(1), c_char_p("a"))
>>>libx.use(res)

上面的代码可能是错误的,只是为了演示我想做什么。

我的问题是,如何保存 create 返回的结果?因为它返回一个指向用户定义的 struct 的指针,而且我不想在 Python 中构造 struct Tag 的对应物,所以 c_void_p 成功了吗?

更新

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

the pointer (c_char_p("a")) is only valid for the duration of the call to create. As soon as create returns then that pointer is no longer valid.

我在 create 中将 c_char_p("a") 分配给 t->name,当调用 create 完成,t->name 是悬空指针吗?因为根据引用的话,该指针在 create 之后不再有效。为什么 c_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);
}

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)

关于python - Python 中的 C 结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9431615/

相关文章:

Python:如何生成每 4 个数字跳过一次的范围?

python - 难以按人口统计提取 IMDb 评级(使用 IMDbpy)

python - 为连接字符串属性指定的值无效

c - 在递归中使用后增量

c++ - MPI_DOUBLE_INT 和 C++ 结构

c - 在 C 中存储整数和通用指针的最便携方法是什么?

python - 当步幅大于 1 时,SAME 填充如何在卷积神经网络中工作?

c - 这个 switch case 语法是什么意思?

使用 getcwd 在 C 字符串中始终获取空值

python - 弃用警告 : struct integer overflow masking is deprecated