假设您有以下C代码:
typedef void (*PythonCallbackFunc)(void* userData);
void cb(PythonCallbackFunc pcf, void* userData)
{
pcf(userData);
}
以及以下Python 3代码:
import ctypes
class PythonClass():
def foo():
print("bar")
CALLBACK_TYPE = ctypes.CFUNCTYPE(None, ctypes.c_void_p)
def callback(userData):
instanceOfPythonClass = ???(userData) #
instanceOfPythonClass.foo()
lib = ctypes.cdll.LoadLibrary("path/to/lib.dll")
pc = PythonClass()
lib.cb(ctypes.byref(pc), CALLBACK_TYPE(callback))
其中“ path / to / lib.dll”是C代码的编译二进制文件.
如何将“回调”中的userData参数转换回PythonClass实例,以便可以调用函数“ foo()”?
解决方法:
dll.c:
#include
#if defined(_WIN32)
# define DLL_EXPORT __declspec(dllexport)
#else
# define DLL_EXPORT
#endif
#define C_TAG "From C"
#define PRINT_MSG_0() printf("%s - [%s] (%d) - [%s]\n", C_TAG, __FILE__, __LINE__, __FUNCTION__)
typedef void (*PythonCallbackFuncPtr)(void *userData);
DLL_EXPORT void callPython(PythonCallbackFuncPtr callbackFunc, void *userData)
{
PRINT_MSG_0();
callbackFunc(userData);
}
code.py:
import sys
from ctypes import CDLL, CFUNCTYPE, \
py_object
CallbackFuncType = CFUNCTYPE(None, py_object)
dll_dll = CDLL("./dll.dll")
call_python_func = dll_dll.callPython
call_python_func.argtypes = [CallbackFuncType, py_object]
class PythonClass():
def foo(self):
print("Dummy Python method")
def callback(userData):
print("From Python: {:s}".format(callback.__name__))
userData.foo()
def main():
instance = PythonClass()
call_python_func(CallbackFuncType(callback), instance)
if __name__ == "__main__":
print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
main()
笔记:
>处理Python类型时,请使用ctypes.py_object(它是PyObject的包装器),而不要使用ctypes.c_void_p
>始终为从Python调用的C函数定义argtypes(和restype)(例如call_python_func(包装callPython))
> PythonClass.foo()缺少第一个(自我)参数,因此只是在PythonClass内部定义的函数而不是方法
>是否进行了其他非关键性更改(主要是重命名)
输出:
06002
标签:python,python-3-x,ctypes