通过ctypes返回给Python的对象如何释放内存?

7 投票
1 回答
3290 浏览
提问于 2025-04-17 02:10

我正在使用ctypes这个工具,把我的C语言函数从MyDll扩展到Python里。

from ctypes import cdll
libX = cdll.LoadLibrary("d:\\MyTestProject\\debug\\MyDll.dll")

在我的.py文件里,有一个类,这个类的方法通过ctypes调用MyDll里的函数。

Class MyTestClass:
       def __init__(self,id):
           libA.MyTestClassInDLL_new.restype = ctypes.c_void_p
           self.obj = libA.MyTestClassInDLL_new(id)

在MyDll中,对应的C语言函数MyTestClassInDLL_new是这样定义的 -

extern "C" __declspec(dllexport) void * MyTestClassInDLL_new(char* id) 
{ 
     pTestObject = new CMyTestClassInDLL(CString(id)); 
     return (void *)pTestObject;    
}

注意,我在我的vc++ DLL里使用new来创建这个对象,并返回它的指针。我在.py文件里把这个函数的返回类型设置为ctypes.c_void_p。

我执行的脚本包含以下内容 -

testob = MyTestClass("5")

这个运行得很好。我在这里得到的testob会被用来进一步调用它的方法,而这些方法内部又会调用MyDll里的C语言函数。

不过,这个对象是通过MyDll里的new创建的,并通过MyTestClassInDLL_new()函数返回的。那么,这个对象该怎么销毁呢?我需要在某个地方使用delete pTestObject,这样它的析构函数才会被调用,进行清理并释放内存。

1 个回答

4

我通常通过添加一个外部的销毁对象函数来处理这个问题,这样我就可以把指针传回去并删除它。

CPP:

SomeClass* createObj()
{
    return new SomeClass();
}

void destroyObj(SomeClass* pObj){
  delete pObj;
  pObj = NULL;
}

H:

extern "C" {
  SomeClass* createObj();
  void destroyObj(SomeClass*);
}

PY:

class SomeObj:
    def __init__(self):
        self.soLib = cdll.LoadLibrary(PATH_SO)
        _createObj = self.soLib.createObj
        _createObj.restype = POINTER(c_long)

        self._objRef = _createObj()
        ## do stuff with self._objRef

    def __del__(self):
        self.soLib.destroyObj(self._objRef)

撰写回答