Python ctypes:在 c 中调用具有自定义类型的函数
Python ctypes: calling a function with custom types in c
我正在尝试包装 pre-existing c code 以便在 Python 中使用 Linux。我对 c 的经验很少,目前正在使用 ctypes 解决这个问题。我的 C 函数需要一个带有自定义类型条目的二维数组,我不知道如何在 python 中重新创建它以将其传递给 c 函数。
这是我尝试调用的函数:
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;
}
头文件已定义
typedef struct Calibration_AIN_t {
float slope;
float offset;
} Calibration_AIN;
其中 NCHAN_18081 和 NGAINS_1808 是常量,udev 是整数。我遵循了关于多维数组的 older question 并尝试制作类似于 c 代码中的结构。
_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)
但这有几个问题:自定义类型 Calibration_AIN 不能像 int 或 float 那样用运算符 * 填充到数组中,我不能通过传递自定义类型到c。我也尝试过使用 Python 中的列表列表制作数组,但我无法将其转换为可通过 ctypes 传递的对 c 有用的任何内容。
如何在不修改 c 代码的情况下从 python 调用此函数?任何帮助将不胜感激,也让我知道我是否应该只学习 c 并尝试用 c 或 Cython 编写我的程序。 Ctypes 可能不是执行此操作的最佳方法。
行:
_fields_ = [("array", (Calibration_AIN() * NCHAN_1808) * NGAINS_1808)]
应该引发 TypeError,因为您 instantiate Calibration_AIN。我相信你的意思是:
_fields_ = [("array", (Calibration_AIN * NCHAN_1808) * NGAINS_1808)]
但即便如此,您也不需要 AINarray 包装器。根据 [Python]: Arrays,你可以这样做:
Calibration_AIN_Table = (Calibration_AIN * NCHAN_1808) * NGAINS_1808
然后,为了初始化实例,请执行以下操作:
>>> 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
我正在尝试包装 pre-existing c code 以便在 Python 中使用 Linux。我对 c 的经验很少,目前正在使用 ctypes 解决这个问题。我的 C 函数需要一个带有自定义类型条目的二维数组,我不知道如何在 python 中重新创建它以将其传递给 c 函数。
这是我尝试调用的函数:
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;
}
头文件已定义
typedef struct Calibration_AIN_t {
float slope;
float offset;
} Calibration_AIN;
其中 NCHAN_18081 和 NGAINS_1808 是常量,udev 是整数。我遵循了关于多维数组的 older question 并尝试制作类似于 c 代码中的结构。
_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)
但这有几个问题:自定义类型 Calibration_AIN 不能像 int 或 float 那样用运算符 * 填充到数组中,我不能通过传递自定义类型到c。我也尝试过使用 Python 中的列表列表制作数组,但我无法将其转换为可通过 ctypes 传递的对 c 有用的任何内容。
如何在不修改 c 代码的情况下从 python 调用此函数?任何帮助将不胜感激,也让我知道我是否应该只学习 c 并尝试用 c 或 Cython 编写我的程序。 Ctypes 可能不是执行此操作的最佳方法。
行:
_fields_ = [("array", (Calibration_AIN() * NCHAN_1808) * NGAINS_1808)]
应该引发 TypeError,因为您 instantiate Calibration_AIN。我相信你的意思是:
_fields_ = [("array", (Calibration_AIN * NCHAN_1808) * NGAINS_1808)]
但即便如此,您也不需要 AINarray 包装器。根据 [Python]: Arrays,你可以这样做:
Calibration_AIN_Table = (Calibration_AIN * NCHAN_1808) * NGAINS_1808
然后,为了初始化实例,请执行以下操作:
>>> 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