在Python中,如何使用ctypes将回调数组作为参数传递给C函数?

问题描述 投票:0回答:1

这是我的问题,我有一个用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(....) ?????

有人有想法吗?

python arrays callback ctypes dynamic-dll-import
1个回答
0
投票

一个简单的示例非常好。我在下面创建了一个,但是如果它对您不起作用,请使用与您的情况相符的类似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
© www.soinside.com 2019 - 2024. All rights reserved.