2015-04-30 69 views
1

的Python 2.7.8,Windows 7中,植酮USB編程器的DLL的Python的ctypes無法通過存儲陣列的結構

我堅持這應該是一個大的存儲器陣列中的數據元素,我一直在使用幾個不同的嘗試的定義,但我不明白錯誤是想告訴我什麼。我遇到的大多數錯誤都是類型錯誤,下面的代碼是我最近的代碼,它似乎在調用函數,但是由於錯誤而沒有進行處理。

C API:

typedef struct tagACI_Memory_Params 
{ 
    UINT Size;    // (in) Size of structure, in bytes 
    UINT BufferNumber;  // (in) Number of buffer of interest, the first buffer number is 0 
    UINT LayerNumber;  // (in) Number of layer of interest, the first layer number is 0 
    DWORD AddressLow;  // (in) Low 32 bits of address, in layer units (natural to device address) 
    DWORD AddressHigh;  // (in) High 32 bits of address, in layer units (natural to device address) 
    PVOID Data;    // (in || out) Pointer to data to read to or write from 
    DWORD DataSize;   // (in) Size of data to read or write, in layer units, max. 16 MB (0x1000000) 
    DWORD FillValue;  // (in) Value to fill buffer with, used by ACI_FillLayer() only 
} ACI_Memory_Params; 

我的Python代碼:

MaxMemorySize = 1024 
MemoryBuffer = ctypes.c_ubyte * MaxMemorySize 

class Memory_Params(ctypes.Structure): 
    _fields_ = [("Size", ctypes.wintypes.UINT), 
       ("BufferNumber", ctypes.wintypes.UINT), 
       ("LayerNumber", ctypes.wintypes.UINT), 
       ("AddressLow", ctypes.wintypes.DWORD), 
       ("AddressHigh", ctypes.wintypes.DWORD), 
       ("Data", MemoryBuffer), 
       ("DataSize", ctypes.wintypes.DWORD), 
       ("FillValue", ctypes.wintypes.DWORD) 
       ] 

WriteLayer = ctypes.windll.ACI.ACI_WriteLayer 
WriteLayer.argtypes = [ctypes.POINTER(Memory_Params)] 
WriteLayer.restype = ctypes.HRESULT 

WData = Memory_Params(ctypes.sizeof(Memory_Params),0,0,0,0,ctypes.POINTER(MemoryBuffer),15,0) 
for i in range(10): 
    WData.Data[i] = i 

print 'write result', WriteLayer(ctypes.byref(WData)) 

API調用返回1,這意味着:在ACI函數定義ACI_ERR_INVALID_PARAMS_SIZE 1 //無效結構尺寸

更新: 我錯過了至關重要的事情:在定義i之後創建並使用MemoryBuffer對象t,以及如何正確定義指針。 如果其他人有類似的情況,在這裏是工作代碼:

MaxMemorySize = 1024 
MemoryBuffer = ctypes.c_ubyte * MaxMemorySize 

class Memory_Params(ctypes.Structure): 
    _fields_ = [("Size", ctypes.wintypes.UINT), 
       ("BufferNumber", ctypes.wintypes.UINT), 
       ("LayerNumber", ctypes.wintypes.UINT), 
       ("AddressLow", ctypes.wintypes.DWORD), 
       ("AddressHigh", ctypes.wintypes.DWORD), 
       ("Data", ctypes.POINTER(ctypes.c_ubyte)), 
       ("DataSize", ctypes.wintypes.DWORD), 
       ("FillValue", ctypes.wintypes.DWORD) 
       ] 
WriteLayer = ctypes.windll.ACI.ACI_WriteLayer 
WriteLayer.argtypes = [ctypes.POINTER(Memory_Params)] 
WriteLayer.restype = ctypes.wintypes.UINT 

PData = MemoryBuffer() 
WData = Memory_Params(ctypes.sizeof(Memory_Params),0,0,0,0,PData,for i in range(10): 
    PData[i] = i 
WriteLayer(ctypes.byref(WData)) 
+0

你不應該糾正的問題。 – CristiFati

回答

1
  • 當初始化WData對象中,6個參數ctypes.POINTER(MemoryBuffer)。這是(或者應該是語法)不正確的:POINTER返回一個指針,當你需要一個unsigned char陣列(這是一個對象或類型的實例
  • ,你得到的尺寸誤差因爲Python結構不符合C之一。所述Data構件在ÇPVOID,這與一個大小爲8的指針(或4,如果你有一個32位的Python),而在的Python它具有的尺寸爲1024
  • MemoryBuffer類型

要解決這個問題,讓你的Memory_Params.Data會員類型:ctypes.POINTER(ctypes.c_ubyte)

+0

爲了澄清,'Data'字段應該被分配一個緩衝器類型的實例,例如, 'Memory_Params(ctypes.sizeof(Memory_Params),Data = MemoryBuffer(),DataSize = 15)'。 'Data'字段將包含緩衝區的地址(假設OP進行了您所建議的更改),並且結構實例將通過其「_objects」字典中的引用保持該緩衝區處於活動狀態。 – eryksun

+0

謝謝你的幫助。它正在工作。 – Blaine