Как передать списки в функцию ctypes на python - PullRequest
0 голосов
/ 02 июля 2018

Это вопрос из 2 частей. Чтобы дать некоторое представление, у меня есть код C следующим образом:

int c_func(const char* dir, float a, float b, float c, float d )
{
    printf("%s\n", dir);
    printf("%f\n",a);
    printf("%f\n",b);
    printf("%f\n",c);
    printf("%f\n",d);

    return 0;
}

Это простая функция, которая принимает строку и 4 числа с плавающей точкой в ​​качестве аргументов и выводит их. Я пытаюсь проверить мой интерфейс phython / C. Мой код Python выглядит следующим образом:

calling_function = ctypes.CDLL("/home/ruven/Documents/Sonar/C interface/Interface.so")  
calling_function.c_func("hello",1, 2, 3, 4])

Теперь, поскольку это работает, вместо того, чтобы передавать 4 отдельных числа, я хотел бы передать список из 4 чисел. Я пробовал другой код в Интернете, чтобы отредактировать свою функцию C, чтобы она использовалась в списке в качестве одного из ее параметров, но я, похоже, не могу понять, как это сделать, так как я новый программист и у меня нет опыта работы с C.

Вопрос 1: Как мне написать функцию C, чтобы принимать список в качестве аргументов?

Вопрос 2: Этот список из четырех чисел на самом деле происходит из списка списков из моего кода на Python. После кодирования функции C смогу ли я использовать массив с именем testfv2[0,:] в качестве входных данных для функции C? testfv2[0,:] - это список измерений 1x4, а testfv2 - это список измерений 117x4. Сейчас я бы хотел добавить в строку функции C по одной строке, поэтому я подумал, используя testfv2[0,:].

1 Ответ

0 голосов
/ 02 июля 2018

Как мне написать функцию C, чтобы принимать список в качестве аргументов?

Короткий ответ, Вы не можете .

Длинный ответ: C не имеет списков, но имеет массивы и указатели.

У вас есть несколько вариантов:

int c_func(const char *dir, float abcd[4]) { // using an array with explicit size

int c_func(const char *dir, float abcd[]) { // Using an array (will decay to a pointer at compile-time)

int c_func(const char *dir, float *abcd) { // Using a pointer.

Если вы когда-либо будете получать только 4 числа с плавающей запятой, я бы предложил первую форму, которая устанавливает размер массива, и любой пользователь (и в основном ваше будущее Я) вашей функции будет знать, что он предоставит только массив из четырех элементов. .

Вызов вашей функции из Python:

floats = [1.0, 2.0, 3.0, 4.0] # Or whatever values you want to pass, but be sure to give only 4
FloatArray4 = ctypes.c_float * 4 # Define a 4-length array of floats
parameter_array = FloatArray4(*floats) # Define the actual array to pass to your C function

Я не знаю, если передача более 4-х чисел к FloatArray4 вызывает ошибку - я думаю, но сейчас я не могу проверить.

Что касается вашего второго вопроса, если вам нужны массивы динамического размера (более 4 элементов), вам понадобится один из двух других профилей для вашей функции C, и в этом случае я советую вам добавить дополнительный int аргумент для размера массива:

int c_func(const char *dir, float floats[], int size) {

или

int c_func(const char *dir, float *floats, int size) {

Вы также можете использовать стандартный size_t вместо int, он предназначен именно для этого.

Если вы хотите передать многомерный массив, вы добавляете еще одну пару скобок:

int c_func(const char *dir, float floats[][4]) { // Note the explicit size for second dimension

но помните, что для массива C для всех измерений, кроме первого, размеры должны быть явно указаны . Если значение является постоянным, это не будет проблемой, однако, если нет, вам придется использовать вместо этого указатель:

int c_func(const char *dir, float *floats[]) {

или

int c_func(const char *dir, float **floats) {

, которые представляют собой два идентичных синтаксиса (массив будет распадаться на указатель). Еще раз, если ваши размеры являются динамическими, я предлагаю добавить параметры для размера.

Если вам нужны дополнительные размеры, просто повторите этот последний шаг.

...