python ctypes,回调函数augment类型是C ++引用

时间:2017-04-17 10:41:30

标签: python c++ c ctypes

我通过ctypes将dll集成到python中,dll需要设置一个回调函数。但是dll回调函数声明如下

void setCallBack(void(*)(Data &a))

Data is C struct, declare as below
typedef struct {
    int index,
    ....
}Data

我不清楚如何通过ctypes设置它,我尝试如下,但返回“WindowsError:[错误-1073741795] Windows错误0xC000001D”错误,您能帮助举例说明如何设置回调。< / p>

mydll = cdll.LoadLibrary("XXX.dll")  
callback_type = CFUNCTYPE(None, POINTER(Data))
callback = callback_type(Data)
mydll.setCallBack(callback)

def dataResponse(data):
    print data.index

class Data(ctypes.Structure):
    _fields_ = [("index", c_int)]

3 个答案:

答案 0 :(得分:0)

您的结构看起来是正确的,但如果您正在调用Windows API,则您的调用约定可能已关闭(您使用的是cdecl,但如果这是Windows API调用,则需要使用stdcall)。

尝试将mydll = cdll.LoadLibrary("XXX.dll")替换为mydll = WinDLL("XXX.dll")

您可能还需要提供一个使用stdcall而不是cdecl的回调函数。如果是,请将CFUNCTYPE切换为WINFUNCTYPE。您正在调用的API应提供有关其预期的详细信息。

看看是否有帮助。

答案 1 :(得分:0)

ctypes不适用于Cpp它只适用于C,您的Cpp函数需要extern "C"链接。
不起作用的原因与Cpp名称修改有关。您的函数void setCallBack(void(*)(Data &a))的名称在Cpp中被标记为_Z11setCallBackPFvR4DataE,但是如果您将extern "C"放入其中(extern "C" void setCallBack(void(*)(Data &a))),它将会出现C修改规则,因此它将被伪造为setCallBack 因此,当您mydll.setCallBack ctypes正在寻找名为setCallBack但未找到它的函数时,它会找到一个名为_Z11setCallBackPFvR4DataE的函数,它无法识别并给您一个错误。

答案 2 :(得分:0)

一个错误是你的回调是包装你的数据结构,而不是你的回调函数。变化:

callback_type = CFUNCTYPE(None, POINTER(Data))
callback = callback_type(Data)
mydll.setCallBack(callback)
def dataResponse(data):
    print data.index

为:

def dataResponse(data):
    print data.index
callback = callback_type(dataResponse)
mydll.setCallBack(callback)

或者您可以使用装饰器语法:

@CFUNCTYPE(None, POINTER(Data))
def dataResponse(data):
    print data.index

mydll.setCallBack(dataResponse)

这是一个完整的例子。还可以使用extern "C"来避免C ++名称错位:

test.cpp(Windows)

struct Data {
    int index;
};

typedef void (*CALLBACK)(Data&);
CALLBACK g_callback;

extern "C" {
    __declspec(dllexport)void setCallBack(CALLBACK f) {
        g_callback = f;
    }

    __declspec(dllexport) void func() {
        Data d;
        d.index = 42;
        if(g_callback)
            g_callback(d);
    }
}

<强> test.py

from ctypes import *

class Data(Structure):
    _fields_ = [('index',c_int)]

CALLBACK = CFUNCTYPE(None,POINTER(Data))

dll = CDLL('test')
dll.setCallBack.argtypes = CALLBACK,
dll.setCallBack.restype = None
dll.func.argtypes = None
dll.restype = None

@CALLBACK
def dataResponse(data):
    print(data.contents.index)

dll.setCallBack(dataResponse)
dll.func()

<强>输出

42