我在使用Python和ctypes时遇到了一些非常奇怪的问题。我使用的是python3.4.3。首先,项目背景:

我用C代码编译了一个自定义dll。我正在使用ctypes与dll接口。C库正在与一些自定义硬件接口。有时,硬件会生成一个中断并将其传递给计算机上的C库。在C API中,有一个原型为void register_callback(int addr, void (*callback)(void))的函数。我有一个回调函数指针数组,它们被初始化为NULL。调用此函数时,index addr处的回调函数指针设置为callback,如下所示:callbacks[addr] = callback;。在

当用户用Python编写程序时,它们会从对不同硬件部件(如按钮或RGB-LED)建模的类中实例化对象。然后,他们可以编写一个自定义回调函数并调用button.register_callback(func)(当然,假设他们有一个名为Button的按钮对象),该对象调用C库中的register_回调函数。现在,当按下按钮并生成中断时,C库将调用适当的回调函数(即callbacks[addr]();)。在

现在,奇怪的是:

在Python中,我第一次尝试在Python中使用register_回调方法,如下所示:class Obj:

def __init__(self, name):
# Initialize stuff
def register_callback(self, func):
CB_T = ctypes.CFUNCTYPE(None)
cb_ptr = CB_T(func)
host_api.register_callback(self.addr, cb_ptr) # host_api is the loaded dll

主要是:

^{pr2}$

当我运行这个,只有“cb2”被打印,不管我按哪个按钮。真正奇怪的是,当我改变注册回调的顺序时:obj2.re

gister_callback(cb2)
obj.register_callback(cb1)

不管我按了什么按钮,只有“cb1”正在打印!在C库中,我(通过printf)验证了根据按钮设置和调用了不同的回调函数指针,但是相同的函数指针被传递给C register_回调函数。在

我通过在register\u回调方法中添加一行来解决这个问题:def register_callback(self, func):

CB_T = ctypes.CFUNCTYPE(None)
cb_ptr = CB_T(func)
(ctypes.cast(cb_ptr, ctypes.POINTER(ctypes.c_int)))
host_api.register_callback(self.addr, cb_ptr)

显然,将cb ptr转换为ctypes指针修复了这个问题——不同的函数指针被传入,我成功地看到“cb1”或“cb2”被打印出来,这取决于我按下的按钮。在

我的问题是,为什么?为什么在转换原函数的时候,调用函数的顺序不同呢?为什么我要改变调用函数的顺序呢?在

我对Python有点初学者,但在C语言方面我更有经验。提前感谢您的回复。在