Форум сайта python.su
0
Здравствуйте, возникла следующая проблема: я не могу понять, как правильно с помощью ctypes передать в C-функцию двумерный массив из python, размер которого задается во время выполнения python-скрипта. В функции требуется изменить элементы двумерного массива. Гугление помогло найти лишь передачу одномерного массива в функцию - это сработало. Но как реализовать мой случай я не понимаю.
Вот пример функции на C, которую требуется вызвать из кода на python. Она перед этим компилируется в динамическую библиотеку.
void changeArray(int arrayLen_1, int arrayLen_2, int **array) { for (int i = 0; i < arrayLen_1; i++) for (int j = 0; j < arrayLen_2; j++) array[i][j] = j+i; }
Офлайн
253
maksimioС такой сигнатурой это вовсе не двумерный массив. Передать то не проблема. Но изготовить такую штуку в питоне будет ой как непросто.
void changeArray(int arrayLen_1, int arrayLen_2, int **array)
Офлайн
0
Двумерные массивы планировал создавать следующим образом:
a = 56 b = 4 array = [[0 for i in range(a)] for k in range(b)]
def read_csi(csi_buf, nr, nc, num_tones): '''Расшифровывает csi из csi_buf, вызывая с помощью ctypes C-функцию''' if nr != 2 or nc != 2 or num_tones != 56: raise TypeError("Error: nr != 2 or nc != 2 or num_tones != 56") csi_re = [[0 for i in range(num_tones)] for k in range(nr * nc)] csi_im = [[0 for i in range(num_tones)] for k in range(nr * nc)] lib = ctypes.CDLL('./libextract_csi.so') lib.read_csi.restype = None lib.read_csi.argtypes = (ctypes.POINTER(ctypes.c_ubyte), ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int), ctypes.POINTER( ctypes.c_int), ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int)) csi_buf = (ctypes.c_ubyte * len(csi_buf))(*csi_buf) for i in range(nr*nc): csi_re[i] = (ctypes.c_int * len(csi_re[i]))(*csi_re[i]) csi_im[i] = (ctypes.c_int * len(csi_im[i]))(*csi_im[i]) lib.read_csi(csi_buf, csi_re[0], csi_re[1], csi_re[2], csi_re[3], csi_im[0], csi_im[1], csi_im[2], csi_im[3]) csi_re[0], csi_re[1], csi_re[2], csi_re[3] = csi_re[0][:], csi_re[1][:], csi_re[2][:], csi_re[3][:] csi_im[0], csi_im[1], csi_im[2], csi_im[3] = csi_im[0][:], csi_im[1][:], csi_im[2][:], csi_im[3][:] return {'re': csi_re, 'im': csi_im}
void read_csi(unsigned char *local_h, int *re0, int *re1, int *re2, int *re3, int *im0, int *im1, int *im2, int *im3)
{
//здесь происходит изменение содержимого всех массивов re и im на основании данных из local_h
}
Офлайн
253
maksimioОчевидно вы ее не решили поскольку решение не соответствует требованиям первого поста.
Сейчас я решил свою проблему
Офлайн
0
Моя цель - повысить производительность. Время которое сожрут списки несущественно относительно времени, которое экономится, если C-функцию запускать с помощью ctypes (проверено профилировщиком). Я пробовал переписать эту функцию на python и не вызывать ее как dll - тогда код работает в 5 раз дольше.
Сейчас я просто хотел бы понять, каким образом я могу подать в C-функцию с помощью ctypes двумерный (а еще лучше многомерный) массив (т.е. массив указателей на указатели в C-функции). Я не знаю, с помощью какого типа данных в python это лучше сделать. У меня мало опыта, поэтому я был бы рад, если бы вы посоветовали что-то на этот счет. Либо я просто по прошествии некоторого времени смогу найти в интернете, как это можно сделать.
Офлайн
253
maksimio
каким образом я могу подать в C-функцию с помощью ctypes двумерный (а еще лучше многомерный) массив (т.е. массив указателей на указатели в C-функции)
Офлайн
857
maksimioНапиши, какую программу делаешь. Неглубокое знание языка C и неглубокое знания языка Python вряд ли приведут к успеху. Так что, если у тебя и программа не сделана ещё, то заниматься повышением её производительности считается ошибкой, которая называется “преждевременная оптимизация”.
Моя цель - повысить производительность.
Офлайн