pythondll

Passing pointers to DLL function in Python


I am working on a project where I have to build a GUI for a development board with python with which I am new to as well. I am given the DLL which has required functions to communicate with the development board. I have LabVIEW equivalent function prototype which looks something like this:

int32_t WriteFPGARegsC(int16_t *USBdev, int32_t *DUTSelect, int32_t *Array_RegsIn, int32_t *Array_RegsOut, int32_t *Array_RegEnable);

And the same prototype also looks like this for Visual Basic:

Public Declare Function WriteFPGARegsC Lib "USB_IO_for_VB6.dll" (ByRef USBdev As Short, ByVal DUTSelect As Integer, ByRef Array_RegsIn As Integer, ByRef Array_RegsOut As Integer, ByRef Array_RegEnable As Integer) As Integer

I am trying to access this function with python instead of LabVIEW because of a lot of issues.

Last three parameters to be passed to the function needs to be an address to an array of 255 elements.

I have no clue how to pass pointers in function in python!!

I wrote the following shortcode to access this function in python:

USBdev = [0]
DUTSelect = [0]
RegsIn = [0] * 255
RegsOut = [0] * 255
RegEnable = [0] * 255

from ctypes import*

mydll = cdll.LoadLibrary("USB_IO_for_VB6.dll")
retmydll = mydll.WriteFPGARegsC(USBdev, DUTSelect, RegsIn, RegsOut, RegEnable)

After executing this code I get following error message:

Traceback (most recent call last):
  File "D:\Kushal\ATLASS\Source_code\Atlass.py", line 12, in <module>
    retmydll = mydll.WriteFPGARegsC(id(USBdev), id(DUTSelect), id(RegsIn),    id(RegsOut), id(RegEnable))
ValueError: Procedure called with not enough arguments (20 bytes missing) or wrong calling convention

Any help will be appreciated!! Thanks a lot!


Solution

  • Listing [Python.Docs]: ctypes - A foreign function library for Python.
    Before everything, check [SO]: C function called from Python via ctypes returns incorrect value (@CristiFati's answer) for a common pitfall when working with CTypes (calling functions).

    Anyway, I prepared a dummy example (don't mind the error proneness), it's just for illustrating the mechanism.

    Output:

    (py35x64_test) e:\Work\Dev\StackOverflow\q051289410> "c:\Install\x86\Microsoft\Visual Studio Community\2015\vc\vcvarsall.bat" amd64
    
    (py35x64_test) e:\Work\Dev\StackOverflow\q051289410> dir /b
    dll00.c
    code00.py
    
    (py35x64_test) e:\Work\Dev\StackOverflow\q051289410> cl /nologo dll00.c /link /DLL /OUT:USB_IO_for_VB6.dll
    dll00.c
      Creating library USB_IO_for_VB6.lib and object USB_IO_for_VB6.exp
    
    (py35x64_test) e:\Work\Dev\StackOverflow\q051289410> dir /b
    dll00.c
    dll00.obj
    code00.py
    USB_IO_for_VB6.dll
    USB_IO_for_VB6.exp
    USB_IO_for_VB6.lib
    
    (py35x64_test) e:\Work\Dev\StackOverflow\q051289410> "e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" ./code00.py
    Python 3.5.4 (v3.5.4:3f56838, Aug  8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] 064BIT on win32
    
    Output register array: 30 31 32 33 34 35 36 37 38 39
            Its 5th element: 35
    
    From C:
            *USBdev: 25
            *DUTSelect: 2
            Array_RegsIn[0]: 20
            Array_RegsOut[0]: 30
            Array_RegEnable[0]: 40
    
            Returning: 99
    
    Function returned: 99
    Output register array: 60 62 64 66 68 70 72 74 76 78
            Its 5th element: 70
    


    Update #0