Python ctypes与C++对象销毁
考虑一下下面这个 Python 的 ctypes 和 C++ 的绑定:
// C++
class A
{
public:
void someFunc();
};
A* A_new() { return new A(); }
void A_someFunc(A* obj) { obj->someFunc(); }
void A_destruct(A* obj) { delete obj; }
# python
from ctypes import cdll
libA = cdll.LoadLibrary(some_path)
class A:
def __init__(self):
self.obj = libA.A_new()
def some_func(self):
libA.A_someFunc(self.obj)
当 Python 对象不再需要时,删除 C++ 对象的最佳方法是什么?
[编辑] 我添加了建议的删除函数,但问题依然存在:这个函数应该由谁来调用,以及什么时候调用。它应该尽可能方便。
3 个回答
2
从DLL中导出一个函数,用来释放对象。这样做是为了确保在释放对象时,使用的内存管理方式和分配对象时是一样的。
2
一般来说,dll(动态链接库)应该提供一种方法来清理它们创建的对象。这样一来,内存的分配就被封装在dll内部。这意味着,你的dll可能需要提供一个像 void A_delete(A*)
这样的清理方法。
10
你可以实现一个叫做 __del__
的方法,这个方法会调用你自己定义的一个析构函数:
C++
class A
{
public:
void someFunc();
};
A* A_new() { return new A(); }
void delete_A(A* obj) { delete obj; }
void A_someFunc(A* obj) { obj->someFunc(); }
Python
from ctypes import cdll
libA = cdll.LoadLibrary(some_path)
class A:
def __init__(self):
fun = libA.A_new
fun.argtypes = []
fun.restype = ctypes.c_void_p
self.obj = fun()
def __del__(self):
fun = libA.delete_A
fun.argtypes = [ctypes.c_void_p]
fun.restype = None
fun(self.obj)
def some_func(self):
fun = libA.A_someFunc
fun.argtypes = [ctypes.c_void_p]
fun.restype = None
fun(self.obj)
另外,注意你在 __init__
方法里漏掉了 self
这个参数。而且,你需要明确指定返回类型和参数类型,因为在 ctypes 中默认是 32 位整数,而在现代系统中,指针通常是 64 位的。
有些人认为 __del__
是不好的做法。作为替代,你可以使用 with
语法:
class A:
def __init__(self):
fun = libA.A_new
fun.argtypes = []
fun.restype = ctypes.c_void_p
self.obj = fun()
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
fun = libA.delete_A
fun.argtypes = [ctypes.c_void_p]
fun.restype = None
fun(self.obj)
def some_func(self):
fun = libA.A_someFunc
fun.argtypes = [ctypes.c_void_p]
fun.restype = None
fun(self.obj)
with A() as a:
# Do some work
a.some_func()