Python ctypes是ctypes.Structure的子类,不为指向结构的指针调用
我包装的C库需要分配和销毁C函数内部结构的内存,并且总是传递指针,而不是结构 我有一个子类Python ctypes是ctypes.Structure的子类,不为指向结构的指针调用,python,python-3.x,ctypes,Python,Python 3.x,Ctypes,我包装的C库需要分配和销毁C函数内部结构的内存,并且总是传递指针,而不是结构 我有一个子类ctypes.Structure,使用\uu del\uu方法。在实例上调用del时不会调用此方法,该实例是指向从C中的函数返回的结构的指针(Foo_init)。有趣的是,当调用del时,如果该实例不是指针,而是从另一个C函数返回的实际值(Foo\u init\u value),就会调用它 如何获取\uuu del\uu方法来调用从C中的函数返回的结构指针 在Python中: import ctypes i
ctypes.Structure
,使用\uu del\uu
方法。在实例上调用del
时不会调用此方法,该实例是指向从C中的函数返回的结构的指针(Foo_init
)。有趣的是,当调用del
时,如果该实例不是指针,而是从另一个C函数返回的实际值(Foo\u init\u value
),就会调用它
如何获取\uuu del\uu
方法来调用从C中的函数返回的结构指针
在Python中:
import ctypes
import gc
libfoo = ctypes.CDLL("libfoo.so")
class Foo(ctypes.Structure):
_fields_ = [
('a', ctypes.c_int),
('b', ctypes.POINTER(ctypes.c_char)),
]
def __del__(self):
print('deleting')
libfoo.Foo_destroy(self)
# Get a pointer to Foo
libfoo.Foo_init.restype = ctypes.POINTER(Foo)
libfoo.Foo_init.argtypes = None
# Get actual Foo, not pointer
libfoo.Foo_init_value.restype = Foo
libfoo.Foo_init_value.argtypes = None
libfoo.Foo_destroy.restype = ctypes.c_int
libfoo.Foo_destroy.argtypes = [ctypes.POINTER(Foo)]
# Get a pointer to Foo
foo = libfoo.Foo_init()
# Nothing is printed here:
del foo
# Nothing is printed here
gc.collect()
# Nothing is printed here
[f for f in gc.get_objects() if isinstance(f, Foo)]
# Get an actual Foo, not pointer
foo = libfoo.Foo_init_value()
# This works, prints 'deleting', but crashes with freeing an invalid pointer
# presumably because __del__ is passing the struct, not pointer to struct
del foo
以下是我的简单C库:
#include <stdlib.h>
typedef struct Foo {
int a;
char *b;
} Foo;
/* Allocate and return pointer to Foo */
/* __del__ does not work for this one */
Foo *Foo_init(void)
{
Foo *foo = (Foo *) malloc(sizeof(Foo));
foo->a = 0;
foo->b = NULL;
return foo;
}
/* Allocate and return value of Foo, not a pointer*/
/* __del__ works on this */
Foo Foo_init_value(void)
{
Foo *foo = Foo_init();
return *foo;
}
int *Foo_destroy(Foo *foo)
{
if (foo->b) {
free(foo->b);
foo->b = NULL;
}
free(foo);
return 0;
}
这是可行的,但我认为有更好的方法:
Foop = ctypes.POINTER(Foo)
def foo_del(self):
print('deleting')
libfoo.Foo_destroy(self)
Foop.__del__ = foo_del
foo = libfoo.Foo_init()
# prints 'deleting'
del foo
什么已经解决,什么可以改变?关于.dll,函数签名可以更改吗?@CristiFati函数签名不能更改;它们来自供应商提供的专有/传统API。
Foop = ctypes.POINTER(Foo)
def foo_del(self):
print('deleting')
libfoo.Foo_destroy(self)
Foop.__del__ = foo_del
foo = libfoo.Foo_init()
# prints 'deleting'
del foo