来自 Windows环境中的DLL.请查看以下代码以了解该问题.
from ctypes import *#---------qsort Callback-------------#IntArray5 = c_int * 5ia = IntArray5(5,1,7,33,99)libc = cdll.msvcrtqsort = libc.qsortqsort.restype = NoneCMPFUNC = CFUNCTYPE(c_int,POINTER(c_int),POINTER(c_int) )test = 0def 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=",testfor item in ia : print item#----------Load DLL & Connect ------------#gobIDLL = WinDLL("C:\LMS\QCWWAN2k.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_callbackdef 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 0callback = proto_callback(py_callback)gobIDLL.SetBytetotalsCallback.restype = c_ulonggobIDLL.SetBytetotalsCallback.argtypes = [proto_callback,c_byte] print "SetBytetotalsCallback = ",gobIDLL.SetBytetotalsCallback(callback,c_byte(256))print "gtx = ",gtxprint "grx = ",grx
DLL记录Prototype和SetBytetotalsCallback()方法的回调,如下所示.
原型:
ulONG QCWWANAPI2K SetSessionStateCallback( tFNSessionState pCallback );
打回来 :
voID BytetotalsCallback( ulONGLONG txTotalBytes,ulONGLONG rxTotalBytes );
输出:
>>> global test= 100001573399Output of connect : 0SetBytetotalsCallback = 0gtx = 0grx = 0>>>>
目前的问题是整个程序被正确调用,
但是根本没有调用python回调.该程序从0状态退出
gobIDLL.SetBytetotalsCallback(callback,c_byte(256))方法,但写的callback()方法
在python中,在调用期间没有调用.
你能指出什么可以帮助进入python回调?
另一个示例qsort()方法奇妙地将指针传递给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).
> GetProcAddress(找一个要打电话的功能).
> Extending Python with C or C++来自Python文档.
以上是内存溢出为你收集整理的Python包装到C回调全部内容,希望文章能够帮你解决Python包装到C回调所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)