1

I've been trying to figure out how to import some c++ functions to python. I got them working until one of the functions needed one of its attributes to be passed by reference and i can't figure out how to make it work. I've been following the advice given here: https://stackoverflow.com/a/252473/7447849 It's been working perfectly until i tried this one:

I have the following c++ function:

bool __stdcall I2CRead(int Instance,  BYTE SlaveAddress, BYTE registerAddress, BYTE* ReadBuff, BYTE Length)

That's the code I've tried:

i2cread_proto = ctypes.WINFUNCTYPE (ctypes.c_bool, ctypes.c_int, ctypes.c_byte, ctypes.c_byte, ctypes.c_byte, ctypes.c_byte)
i2cread_Params = (1, "instance", 0),(1, "SlaveAddress", 0),(1, "registerAddress", 0),(1, "ReadBuff", 0),(1, "Length", 0), # (parameter direction (1 for input, 2 for output), parameter name, default value)

i2cread = i2cread_proto (("I2CRead", qsfp_lib), i2cread_Params)

readBuff = ctypes.c_byte(0)

if (i2cread(0, 160, address, readBuff, 1)==True):
    print(readBuff)
else:
    print('Could not read data')

This code works but readBuff stays the same default value given instead of changing as it should.

I tried to use byref() but still not working (it gives me an wrong type error).

Any insights on i might be doing wrong? I am not too skilled in Python so maybe there's a concept i'm misunderstanding

  • If I'm not mistaken, `ctypes.c_byte(0)` just returns a single-byte value initialized to zero ? Which would explain while using it as a buffer doesn't work. – etene Jul 13 '18 at 13:59
  • *C* (*Win*)'s `BYTE*` translates into *ctypes* as `ctypes.POINTER(ctypes.c_ubyte)`(`BYTE` is unsigned). Also, since `ReadBuff` (as its name suggests) is a buffer, you should initialize it to smth like: `readBuff = (ctypes.c_ubyte * BUF_MAX_LEN)()` where `BUF_MAX_LEN = 255` (or any value other than 255, you should know better; put this line **before** the previous one). – CristiFati Jul 13 '18 at 20:58
  • Seriously, use `cffi`, it makes life *much* easier/safer. – o11c Jul 14 '18 at 03:08

1 Answers1

0

Untested. Make sure you use the correct types for arguments.

from ctypes import *
dll = WinDLL('dllname')
dll.I2CRead.argtypes = c_int,c_ubyte,c_ubyte,POINTER(c_ubyte),c_ubyte
dll.I2CRead.restype = c_bool

output = (c_ubyte * 256)()  # Create instance of a c_ubyte array to store the output.
result = dll.I2CRead(1,2,3,output,len(output))
Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251