2

Python 2.7.8, Windows 7, Phyton USB programmer's DLL

I am stuck with the Data element which should be a large memory array, I have tried using several different definitions, but I cannot understand what the errors are trying to tell me. Most of the errors I have encountered have been type errors, this code below is the closest I have been, it seems to be calling the function, but it does not process due to the error.

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;

My python code:

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

The API call returns a 1 which means: define ACI_ERR_INVALID_PARAMS_SIZE 1 // Invalid structure size in ACI function

Update: The critical things I missed: Creating and using the MemoryBuffer object after defining it, and how to correctly define the pointer. If anyone else has a similar situation, here is working code:

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))
1
  • You shouldn't have corrected the question. Commented Feb 20, 2018 at 9:55

1 Answer 1

2
  • When you initialize the WData object, the 6th argument is ctypes.POINTER(MemoryBuffer). This is (or should be syntactically) incorrect: POINTER returns a pointer type, while you need an unsigned char array (which is an object or an instance of a type)
  • The size error that you get is because the Python structure doesn't match the C one. The Data member in C is a PVOID, which is a pointer with a size of 8 (or 4 if you have a 32bit Python), while in Python it has the MemoryBuffer type which has a size of 1024

To correct the problem, make your Memory_Params.Data member's type: ctypes.POINTER(ctypes.c_ubyte)

Sign up to request clarification or add additional context in comments.

2 Comments

Just to clarify, the Data field should be assigned an instance of the buffer type, e.g. Memory_Params(ctypes.sizeof(Memory_Params), Data=MemoryBuffer(), DataSize=15). The Data field will contain the address of the buffer (assuming the OP makes the change you suggested), and the structure instance will keep the buffer alive with a reference in its _objects dict.
Thank you both for your assistance. It is working now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.