从 C/C++ 调用 python 方法,并在访问冲突异常中失败
Call a python method from C/C++, and fail in access violation exception
我们想在 python 中调用一个 c/c++ 扩展,在扩展中我们需要回调 python 脚本中的一个函数。
这是 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("callFunc\n");
//PyObject* ret = PyObject_CallMethod(self, "func", NULL);
PyObject* ret2 = PyObject_CallFunctionObjArgs(PyObject_GetAttrString(self, (char*)"func") , self, NULL);
printf("callFunc2\n");
return 0;
}
我们尝试了两种方法(PyObject_CallFunctionObjArgs / PyObject_CallMethod),两种方法都没有调用失败。结果显示:
Traceback (most recent call last):
File "test\tCall.py", line 19, in <module>
mDll.callFunc(c)
WindowsError: exception: access violation writing 0x0000000C
我们怎么称呼 MyClass.func ?
ctypes
在调用使用 CDLL
加载的任何内容之前释放 GIL。你需要显式持有它,或者使用ctypes.PyDLL
,或者实际上,最好只写一个普通的扩展模块而不是手动加载DLL。
此外,管理你的引用,不要将 self
传递给 func
方法;那是隐式发生的。
(我不知道这些是不是所有的问题,但这些是我注意到的。)
我们想在 python 中调用一个 c/c++ 扩展,在扩展中我们需要回调 python 脚本中的一个函数。
这是 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("callFunc\n");
//PyObject* ret = PyObject_CallMethod(self, "func", NULL);
PyObject* ret2 = PyObject_CallFunctionObjArgs(PyObject_GetAttrString(self, (char*)"func") , self, NULL);
printf("callFunc2\n");
return 0;
}
我们尝试了两种方法(PyObject_CallFunctionObjArgs / PyObject_CallMethod),两种方法都没有调用失败。结果显示:
Traceback (most recent call last):
File "test\tCall.py", line 19, in <module>
mDll.callFunc(c)
WindowsError: exception: access violation writing 0x0000000C
我们怎么称呼 MyClass.func ?
ctypes
在调用使用 CDLL
加载的任何内容之前释放 GIL。你需要显式持有它,或者使用ctypes.PyDLL
,或者实际上,最好只写一个普通的扩展模块而不是手动加载DLL。
此外,管理你的引用,不要将 self
传递给 func
方法;那是隐式发生的。
(我不知道这些是不是所有的问题,但这些是我注意到的。)