这是我的问题,我有一个用C这样的API编写的旧版库(.so):
typedef void (*CALLBACK)( void);
typedef CALLBACK CALLBACK_TBL[ 5 ];
void init(CALLBACK_TBL callbackTbl)
{
T_MYCALLBACK *myCallback1 = (T_MYCALLBACK *)(callbackTbl[0]);
if (myCallback1 )
{
myCallback1(2,3);
}
}
当然,因为它是旧式库,所以我不能更改API签名。
现在从Python,我正在尝试使用在python中定义的回调来调用init:
CallbackType1 = ctypes.CFUNCTYPE(None, c_ulong, c_ulong)
CallbackType2 = ctypes.CFUNCTYPE(None, c_ubyte, c_ubyte)
...
CallbackType5 = ctypes.CFUNCTYPE(None, c_int32, c_int32)
def callback1(long1, long2):
print("callback1")
def callback2(bool1, bool2):
print("callback2")
...
def callback5(int1, int2):
print("callback5")
但是我无法理解如何进行这样的回调数组:
_callback1 = CallbackType1(callback1)
_callback2 = CallbackType1(callback2)
...
_callback5 = CallbackType1(callback5)
lib = CDLL("lib.so")
lib.init(....) ?????
有人有想法吗?
一个简单的示例非常好。我在下面创建了一个,但是如果它对您不起作用,请使用与您的情况相符的类似DLL示例来更新您的问题:
test.cpp
typedef void (*CALLBACK)(void);
typedef CALLBACK CALLBACK_TBL[3];
extern "C" __declspec(dllexport)
void init(CALLBACK_TBL callbackTbl)
{
for(int i = 0; i < 3; ++i)
callbackTbl[i]();
}
test.py
from ctypes import *
CALLBACK = CFUNCTYPE(None)
CALLBACK_TBL = CALLBACK * 3
@CALLBACK
def callback1():
print('callback1')
@CALLBACK
def callback2():
print('callback2')
@CALLBACK
def callback3():
print('callback3')
cbt = CALLBACK_TBL(callback1,callback2,callback3)
dll = CDLL('./test')
dll.init.argtypes = CALLBACK_TBL,
dll.init.restype = None
dll.init(cbt)
输出:
callback1
callback2
callback3