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.
解决方案
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