python ctypes,回调函数的扩充类型是C++;参考

python ctypes,回调函数的扩充类型是C++;参考,python,c++,c,ctypes,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:[Error-1073741795]Windows Erro

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

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

Data is C struct, declare as below
typedef struct {
    int index,
    ....
}Data
我不清楚如何通过ctypes进行设置,我尝试如下,但返回“WindowsError:[Error-1073741795]Windows Error 0xC000001D”错误,您能否帮助给出一个如何设置回调的示例

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)]

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

尝试将
mydll=cdll.LoadLibrary(“XXX.dll”)
替换为
mydll=windl(“XXX.dll”)

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


看看这是否有帮助

ctypes不适用于Cpp它只适用于C,您的Cpp函数需要有
extern“C”
链接。
不起作用的原因与Cpp名称损坏有关。函数名
void setCallBack(void(*)(Data&a))
在Cpp中被损坏为
\u z11setcallbackpfvr4data
,但是如果您将
extern“C”
放在它的开头(
extern“C”void setCallBack(void(*)(Data&a))
,它将被损坏为
setCallBack

因此,当您执行
mydll.setCallBack
ctypes正在查找名为
setCallBack
的函数,但未找到它时,它会找到名为
\u z11setCallbackpfvr4data
的函数,但它无法识别该函数,并且会给您一个错误。

一个错误是您的回调正在包装数据结构,不是你的回调函数。更改:

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

也可以使用decorator语法:

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

mydll.setCallBack(dataResponse)
这里有一个完整的例子。还使用<代码>外部“C”<代码>以避免C++名称的篡改:

test.cpp(Windows)

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()
输出

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);
    }
}
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