2

I'm trying to wrap pre-existing c code for use in Python in Linux. I have little experience with c, and I'm currently approaching this problem using ctypes. My C function requires a 2d array with custom type entries and I don't know how to recreate this in python to pass it to the c function.

Here is the function I'm attempting to call:

void usbBuildGainTableAI_USB1808(libusb_device_handle *udev, Calibration_AIN table[NCHAN_1808][NGAINS_1808])
{

  int i, j;
  uint16_t address = 0x7000;  // base address of ADC calibration coefficients.

  for (i = 0; i < NCHAN_1808; i++) {
    for (j = 0; j < NGAINS_1808; j++) {
      usbMemAddressW_USB1808(udev, address);
      usbMemoryR_USB1808(udev, (uint8_t *) &table[i][j].slope, sizeof(float));
      address += 4;
      usbMemAddressW_USB1808(udev, address);
      usbMemoryR_USB1808(udev, (uint8_t *) &table[i][j].offset, sizeof(float));
      address += 4;
    }
  }
  return;
}

The header file has defined

typedef struct Calibration_AIN_t {
  float slope;
  float offset;
} Calibration_AIN;

where NCHAN_18081 and NGAINS_1808 are constants and udev is an integer. I've followed an older question regarding multidimensional arrays and attempted to make a structure like the one in the c code.

_1808 = CDLL(os.path.abspath("lib1808.so"))

NCHAN_1808 = 8  # max number of A/D channels in the device
NGAINS_1808 = 4  # max number of gain levels

class Calibration_AIN(Structure):
    _fields_ = [("slope", c_float), ("offset", c_float)]

class AINarray(Structure):
    _fields_ = [("array", (Calibration_AIN() * NCHAN_1808) * NGAINS_1808)]

table_AIN = AINarray()

_1808.usbBuildGainTableAI_USB1808(udev, table_AIN)

But there's a couple problems with this: the custom type Calibration_AIN can't be populated in an array with the operator * like an int or float can, and I can't pass a custom type through to c. I've also tried making the array with a list of lists in Python, but I can't convert that to anything useful to c passable through ctypes.

How can I call this function from python without modifying the c code? Any help would be much appreciated, and also let me know if I should just learn c and try to write my program in c or Cython. Ctypes may not be the best way of doing this.

1 Answer 1

0

The line:

_fields_ = [("array", (Calibration_AIN() * NCHAN_1808) * NGAINS_1808)]

should raise a TypeError, since you instantiate Calibration_AIN. I believe that what you meant was:

_fields_ = [("array", (Calibration_AIN * NCHAN_1808) * NGAINS_1808)]

But even so, you don't need the AINarray wrapper. According to [Python]: Arrays, you could do something like:

Calibration_AIN_Table = (Calibration_AIN * NCHAN_1808) * NGAINS_1808

and then, in order to initialize an instance do smth like:

>>> cat = Calibration_AIN_Table()
>>> for i in range(NGAINS_1808):
...     for j in range(NCHAN_1808):
...         cat[i][j].slope = i * j
...         cat[i][j].offset = i * i * j
...
>>> cat[2][3].slope
6.0
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your reply. When I do this I get an error on the line cat[i][j].slope = i * j TypeError: _cytpes.PyCArrayType object does not support indexing
cat = Calibration_AIN_Table(), cat should be an instance note the () after Calibration_AIN_Table.

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.