我们想在python中调用一个c/c++扩展,在扩展中我们需要回调python脚本中的一个函数。
这是蟒蛇代码
# -*- coding: UTF-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
import ctypes
class MyClass:
def func(self):
print "func"
open("out.txt","w").write("func")
print "func2"
return
mDll = ctypes.CDLL("xx.dll", ctypes.RTLD_GLOBAL)
c = MyClass()
# c.func() is what we wanna run below
mDll.callFunc.argtypes = [ctypes.py_object]
mDll.callFunc(c)
下面是 xx.dll 的 c 源代码,由 VS 2008 构建:
__declspec(dllexport) int callFunc(PyObject* self){
printf("callFuncn");
//PyObject* ret = PyObject_CallMethod(self, "func", NULL);
PyObject* ret2 = PyObject_CallFunctionObjArgs(PyObject_GetAttrString(self, (char*)"func") , self, NULL);
printf("callFunc2n");
return 0;
}
我们尝试了两种方法(PyObject_CallFunctionObjArgs/PyObject_CallMethod(,这两种方法都没有在调用中失败。结果显示:
Traceback (most recent call last):
File "testtCall.py", line 19, in <module>
mDll.callFunc(c)
WindowsError: exception: access violation writing 0x0000000C
我们怎么能称呼MyClass.func?
ctypes
在调用任何加载了CDLL
的东西之前释放 GIL。您需要显式持有它,或使用ctypes.PyDLL
,或者实际上,最好只编写一个普通的扩展模块,而不是手动加载 DLL。
另外,管理您的引用,不要将self
传递给 func
方法;这是隐式发生的。
(我不知道这些是否是所有的问题,但这些都是我注意到的问题。