2017-04-17 58 views
1

我通過ctypes的一個dll集成到蟒,該DLL需要設置的回調函數。但該dll回調函數聲明如下蟒ctypes的,回調函數擴充類型是C++參考

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

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

我並不清楚如何通過ctypes的設置它,我嘗試如下,但返回「WindowsError:[錯誤-1073741795] Windows錯誤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)] 

回答

0

你的結構看起來是正確的,但如果你打電話到Windows API的調用約定可能關閉(你使用的cdecl,但如果這是一個Windows API調用,需要STDCALL)。

嘗試mydll = WinDLL("XXX.dll")

更換mydll = cdll.LoadLibrary("XXX.dll")您可能還需要提供使用的STDCALL代替CDECL一個回調函數。如果是這樣,請將CFUNCTYPE切換爲WINFUNCTYPE。您要調用的API應提供有關其預期的詳細信息。

,看看有沒有幫助。

+0

我更改爲WINFUNCTYPE,錯誤也存在。 – Eric

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的函數,它不會識別並給出錯誤。

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(視窗)

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