你问的是你的例子中唯一的问题。 只是为了回答刚才您的问题:您必须注释C函数返回类型,以便ctypes知道它是一个内存地址 - 否则它默认为(4字节)整数(而在任何64字节操作系统中,指针长8个字节)。
然后你就可以在你点类使用(隐藏) “FROM_ADDRESS”方法来创建Python端POINT结构:
test_lib.get_point.restype = c_void_p
p = POINT.from_address(test_lib.get_point())
print(p.x, p.y)
之前的作品,但是,你有一个更根本的问题在C方: 您在示例中声明的POINT结构仅在get_point
正在运行时存在,并在之后解除分配。上面的代码会导致分段错误。
您的C代码必须正确分配内存。此外,您应该采取措施解除分配您在C中分配的数据结构 - 否则您将会发生内存泄漏,因为每次调用C中的函数都会分配更多的内存,并且不会释放内存。 (请注意,当Python POINT对象超出范围时,该内存不会自行释放)。
您的C代码可能是这样的:
#include <stdlib.h>
#include <stdio.h>
typedef struct point {
int x;
int y;
} POINT;
POINT *get_point()
{
POINT *p;
POINT initial = {1, 2};
p = malloc(sizeof(POINT));
*p = initial;
return p;
}
void free_point(POINT *p)
{
free(p);
}
而与此Python的一部分:
from ctypes import *
import os
lib_name = '/testlib.so'
test_lib = CDLL(os.getcwd() + lib_name)
class POINT(Structure):
_fields_ = [('x', c_int),
('y', c_int)]
test_lib.get_point.restype = c_void_p
p1 = POINT.from_address(test_lib.get_point())
print (p1.x, p1.y)
test_lib.free_point(byref(p1))
del p1
一切都应该只是工作。
(只是让这个答案是一个完整的ctypes的例子,我将添加 GCC命令编译TESTLIB文件:
gcc -c -fPIC test.c -o test.o
gcc test.o -shared -o testlib.so
)
您可以用标记为'typedef的任何原因'ed'struct'?很无用。如果你不明白这个评论,你必须在开始之前学习'struct's和'typedef'。 – Olaf
@Olaf我一直使用'typedef'作为C中'struct'的别名。那有什么内在的错误吗? –
我没有评论使用'typedef'。但是你的评论证明我的假设是正确的。不要只遵循一种模式,但要学习**为什么**你必须/应该写一些特定的方式! – Olaf