Python包装到C回调
尝试创建一个需要在调用C回调时调用的
python回调
来自 Windows环境中的DLL.请查看以下代码以了解该问题. from ctypes import * #---------qsort Callback-------------# IntArray5 = c_int * 5 ia = IntArray5(5,1,7,33,99) libc = cdll.msvcrt qsort = libc.qsort qsort.restype = None CMPFUNC = CFUNCTYPE(c_int,POINTER(c_int),POINTER(c_int) ) test = 0 def py_cmp_func(a,b): #print 'py_cmp_func:',a[0],b[0] global test test = 10000 return a[0]-b[0] cmp_func = CMPFUNC(py_cmp_func) qsort(ia,len(ia),sizeof(c_int),cmp_func) print "global test=",test for item in ia : print item #----------Load DLL & Connect ------------# gobiDLL = WinDLL("C:LMSQCWWAN2k.dll") print 'Output of connect : ',gobiDLL.QCWWANConnect() #----------SetByteTotalsCallback----------# tx = POINTER(c_ulonglong) rx = POINTER(c_ulonglong) proto_callback = WINFUNCTYPE(c_void_p,tx,rx) gtx = grx = 0 # Used to copy the response in the py_callback def py_callback(t,r): sleep(10) print 'python callback ...' print "tx=",t,"rx=",r global gtx,grx gtx = 5000 # gtx = t grx = 2000 # grx = r #return 0 callback = proto_callback(py_callback) gobiDLL.SetByteTotalsCallback.restype = c_ulong gobiDLL.SetByteTotalsCallback.argtypes = [proto_callback,c_byte] print "SetByteTotalsCallback = ",gobiDLL.SetByteTotalsCallback(callback,c_byte(256)) print "gtx = ",gtx print "grx = ",grx DLL记录Prototype和SetByteTotalsCallback()方法的回调,如下所示. 原型: ULONG QCWWANAPI2K SetSessionStateCallback( tFNSessionState pCallback ); 打回来 : void ByteTotalsCallback( ULONGLONG txTotalBytes,ULONGLONG rxTotalBytes ); 输出: >>> global test= 10000 1 5 7 33 99 Output of connect : 0 SetByteTotalsCallback = 0 gtx = 0 grx = 0 >>>> 目前的问题是整个程序被正确调用, 你能指出什么可以帮助进入python回调? TIA, 安东尼 解决方法
你不能. C/C++函数无法直接访问Python函数 – 函数原型可能需要指向C的指针.Python将向其传递指向其特定函数的内部数据结构的指针.
这是构建python的C扩展以包装该DLL并将其暴露给Python的时候.你要做的就是用C回调调用Python回调,因为可以做到.更清楚的是,您想要实现的目标是: | This side is C land i.e. "real" addresses | Python objects --> C extension -- register callback with --> DLL | | in the python | Calls callback | | interpreter <-------------- Callback in C extension <------- | 以下是从C构建调用python函数的一个非常快速的解释.您需要使用用于构建Python发行版的MSVC(或替代工具)来构建此代码;使用depends.exe找出它链接的msvcXX.dll. 全局状态通常被认为是坏的,但为了简单起见,我使用的是: static PyObject* pyfunc_event_handler = NULL; static PyObject* pyfunc_event_args = NULL; 然后我添加了一个set handler函数,以便更容易地设置回调.但是,您不需要这样做,您只需要 static PyObject* set_event_handler(PyObject *self,PyObject *args) { PyObject *result = NULL; PyObject *temp; 下一行是重要的一行 – 我允许传递两个python对象(PyArg_ParseTuple的O参数.一个对象包含函数,另一个包含其参数. if (PyArg_ParseTuple(args,"OO",&temp,&pyfunc_event_args)) { if (!PyCallable_Check(temp)) { PyErr_SetString(PyExc_TypeError,"parameter must be a function"); return NULL; } 整理参考. Python需要你这样做. Py_XINCREF(temp); /* Add a reference to new func */ Py_XDECREF(pyfunc_event_handler); /* Dispose of previous callback */ pyfunc_event_handler = temp; /* Remember new callback */ /* Boilerplate to return "None" */ Py_INCREF(Py_None); result = Py_None; } return result; } 然后你可以在其他地方调用它: PyObject* arglist = Py_BuildValue("(O)",pyfunc_event_args); pyobjresult = PyObject_CallObject(pyfunc_event_handler,arglist); Py_DECREF(arglist); 不要忘记DECREF,你需要Python来gc arglist. 从python中,使用它就像这样简单: set_event_handler(func,some_tuple) 其中func具有匹配的参数,如下所示: def func(obj): /* handle obj */ 您可能想要阅读的内容: > LoadLibrary(从C加载DLL). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |