从 C/C++ 调用 python 方法,并在访问冲突异常中失败



我们想在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 方法;这是隐式发生的。

(我不知道这些是否是所有的问题,但这些都是我注意到的问题。

最新更新