У меня есть некоторые функции, написанные на C, которые я хочу вызывать из Python, используя ctypes.Преобразование базовых типов данных Python в типы данных C, такие как int, float, double и т. Д. С помощью ctypes, довольно легко, но когда дело доходит до массивов, у меня возникают некоторые проблемы.
Насколько я знаю, есть 3 "формы«из массивов.В объявлениях функций вы можете объявить эти формы несколькими способами.Для простоты давайте взглянем на целочисленные массивы.
1D Массив целых чисел в C
1-мерный массив часто объявляется и инициализируется следующим образом:
int foo[5] = {1, 2, 3, 4, 5];
В объявлениях функций это может выглядеть следующим образом:
void func(int foo[5], int len);
void func(int foo[], int len);
void func(int *foo, int len);
1D Массив целочисленных указателей в C
Эти массивы часто путают с 2D-массивами AFAIK.Но они разные.Это массивы, которые содержат указатели.Таким образом, массив, который содержит адреса памяти целочисленных переменных в нашем примере.Они объявлены так:
int *foo[5];
Это массив из 5 указателей int.НЕ указатель на массив из 5 дюймов ... В объявлении функции они выглядят так:
void func(int *foo[5], int len);
void func(int *foo[], int len);
void func(int **foo, int len);
2D-массив целых чисел в C
2D-массив объявляется так:
int foo[2][5];
В объявлениях функций они выглядят так:
void func(int foo[2][5], int rows, int columns);
void func(int foo[][5], int rows, int columns);
void func(int (*foo)[5], int rows, int columns);
void func(int *foo, int rows, int columns);
В последнем объявлении вы даете адрес памяти первого элемента foo [0], например: &foo[0][0]
или foo[0]
и вам действительно нужно дать и строки, и столбцы!
Вопросы
Теперь мои вопросы:
- Как следует ctypes.argtypesвыглядеть для каждой из этих 3 форм массива?
- Как создать и преобразовать массив NumPy в формат ctypes для каждой из этих трех форм массива?
- Как преобразовать каждый из этих трех массивов массивов типа ctype обратно в массивы NumPy?
1) Я предполагаю, что свойство ctypes.argtypes для каждой формы выглядит следующим образом:
- 1D массив целых чисел:
ctypes.POINTER(ctypes.c_int)
- 1D массив целочисленных указателей:
ctypes.POINTER(ctypes.POINTER(ctypes.c_int))
и ctypes.POINTER(ctypes.c_int) * 5
в случае int *foo[5]
? - 2D массив целых чисел: в случае
int (*foo)[5]
: ctypes.POINTER(ctypes.c_int * 5)
И в случае int foo[2][5]
: (ctypes.c_int*5)*2
В случае int *foo
: ctypes.POINTER(ctypes.c_int)
2) Я прочитал, что могу использовать атрибут ctypes numpy.ndarrayМетод data_as для преобразования массива Numpy в определенный формат ctypes?Поэтому, учитывая мой массив форм:
1D Целочисленный массив:
data = numpy.array([[0.1, 0.1], [0.2, 0.2], [0.3, 0.3]])
ctypes_format = data.ctypes.data_as(ctypes.POINTER(ctype.c_int))
1D Целочисленный массив указателей
data = numpy.array([[0.1, 0.1], [0.2, 0.2], [0.3, 0.3]])
ctypes_format = data.ctypes.data_as(ctypes.POINTER(ctypes.POINTER(ctype.c_int)))
Я не уверен, что это правильно ...
2D Integer Array
data = numpy.array([[0.1, 0.1], [0.2, 0.2], [0.3, 0.3]])
data.ctypes.data_as(ctypes.POINTER(ctype.c_int))
Или в случае (*foo)[5]
:
data = numpy.array([[0.1, 0.1], [0.2, 0.2], [0.3, 0.3]])
data.ctypes.data_as(ctypes.POINTER(ctypes.c_int * 5))
Также не уверен, что это правильно
3) Теперь мой последний вопрос - как я могу преобразовать эти массивы C / ctypes обратно в массивы NumPy.Я действительно понятия не имею ...