Python-сообщество
![]()
- Начало
- » Python для новичков
- » ctypes — как изменить в функции содержимое двумерного массива?
#1 Март 15, 2020 20:12:18
maksimio Зарегистрирован: 2020-03-15 Сообщения: 3 Репутация: 0 Профиль Отправить e-mail
ctypes — как изменить в функции содержимое двумерного массива?
Здравствуйте, возникла следующая проблема: я не могу понять, как правильно с помощью 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; >
#2 Март 15, 2020 22:32:04
doza_and От: Зарегистрирован: 2010-08-15 Сообщения: 4138 Репутация: 252 Профиль Отправить e-mail
ctypes — как изменить в функции содержимое двумерного массива?
maksimio
void changeArray(int arrayLen_1, int arrayLen_2, int **array)
С такой сигнатурой это вовсе не двумерный массив. Передать то не проблема. Но изготовить такую штуку в питоне будет ой как непросто.
Приведите код на питоне которым вы собрались создавать этот “двумерный массив”.
#3 Март 16, 2020 00:15:08
maksimio Зарегистрирован: 2020-03-15 Сообщения: 3 Репутация: 0 Профиль Отправить e-mail
ctypes — как изменить в функции содержимое двумерного массива?
Двумерные массивы планировал создавать следующим образом:
a = 56 b = 4 array = [[0 for i in range(a)] for k in range(b)]
Сейчас я решил свою проблему, сколхозив передачу нескольких одномерных массивов в C-функцию. Пока это сгодится, но мне желательно бы иметь возможность изменять произвольное количество массивов, а не 8, как в коде ниже.
Код на Python функции, которая собирает C-функцию с помощью ctypes:
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
>
#4 Март 16, 2020 06:48:52
doza_and От: Зарегистрирован: 2010-08-15 Сообщения: 4138 Репутация: 252 Профиль Отправить e-mail
ctypes — как изменить в функции содержимое двумерного массива?
maksimio
Сейчас я решил свою проблему
Очевидно вы ее не решили поскольку решение не соответствует требованиям первого поста.
В С не бывает двумерных массивов с переменными размерностями. Поэтому чисто формально передать туда такое нельзя.
Точнее непонятно в чем ваша проблема.
Это учебная задача? Нет -тогда нельзя менять интерфейс.
Вы хотите повысить быстродействие? Нет. Очевидно что все ваши манипуляции с массивами сожрут производительность. Тогда вы бы работали с данными лежащими в памяти подряд. Те нельзя работать со списками питона. Вместо них надо либо struct использовать либо что-то типа (ctypes.c_int*3)*5 либо numpy.array.
Вы делаете интерфейс к готовой системе? Нет. Сложность зашкаливает. В этом случае вы бы использовали boost python, pybind11, swig, cython или другие средства для этого предназначенные.
#5 Март 17, 2020 16:59:05
maksimio Зарегистрирован: 2020-03-15 Сообщения: 3 Репутация: 0 Профиль Отправить e-mail
ctypes — как изменить в функции содержимое двумерного массива?
Моя цель — повысить производительность. Время которое сожрут списки несущественно относительно времени, которое экономится, если C-функцию запускать с помощью ctypes (проверено профилировщиком). Я пробовал переписать эту функцию на python и не вызывать ее как dll — тогда код работает в 5 раз дольше.
Сейчас я просто хотел бы понять, каким образом я могу подать в C-функцию с помощью ctypes двумерный (а еще лучше многомерный) массив (т.е. массив указателей на указатели в C-функции). Я не знаю, с помощью какого типа данных в python это лучше сделать. У меня мало опыта, поэтому я был бы рад, если бы вы посоветовали что-то на этот счет. Либо я просто по прошествии некоторого времени смогу найти в интернете, как это можно сделать.
#6 Март 17, 2020 20:46:48
doza_and От: Зарегистрирован: 2010-08-15 Сообщения: 4138 Репутация: 252 Профиль Отправить e-mail
ctypes — как изменить в функции содержимое двумерного массива?
maksimio
каким образом я могу подать в C-функцию с помощью ctypes двумерный (а еще лучше многомерный) массив (т.е. массив указателей на указатели в C-функции)
Вы наверное не очень хорошо знаете C. Поэтому я еще раз вам повторю. Двумерный массив и массив указателей на указатели это совершенно разные типы.
Для второго нормальных аналогов в питоне нет.
#7 Март 17, 2020 23:31:40
py.user.next От: Зарегистрирован: 2010-04-29 Сообщения: 9675 Репутация: 841 Профиль Отправить e-mail
ctypes — как изменить в функции содержимое двумерного массива?
maksimio
Моя цель — повысить производительность.
Напиши, какую программу делаешь. Неглубокое знание языка C и неглубокое знания языка Python вряд ли приведут к успеху. Так что, если у тебя и программа не сделана ещё, то заниматься повышением её производительности считается ошибкой, которая называется “преждевременная оптимизация”.
передача массива в функцию на питоне [закрыт]
Закрыт. Этот вопрос необходимо уточнить или дополнить подробностями. Ответы на него в данный момент не принимаются.
Хотите улучшить этот вопрос? Добавьте больше подробностей и уточните проблему, отредактировав это сообщение.
Закрыт 4 года назад .
Как на питоне передать массив на выход в функцию? Делаю минимализацию по методу квайна, там очень полезно будет это использование.
Отслеживать
задан 5 окт 2019 в 5:35
Артём Подковыров Артём Подковыров
35 1 1 золотой знак 1 1 серебряный знак 5 5 бронзовых знаков
Так же, как аргумент любого другого типа.
5 окт 2019 в 5:59
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Под массивом вы скорее всего имеете в виду list? Не совсем понятно в чем проблема его передачи в функцию:
def my_function(some_list): #code pass my_function([1, 2, 3, 4, 5])
Или предварительно записав его в переменную
my_list = [1, 2, 3, 4, 5] my_function(my_list)
Отслеживать
ответ дан 5 окт 2019 в 8:04
Константин Комиссаров Константин Комиссаров
2,536 15 15 серебряных знаков 35 35 бронзовых знаков
invalid syntax же!
5 окт 2019 в 16:35
@andreymal где? почему?
5 окт 2019 в 16:37
Вы сами-то пробовали первый пример запустить?
5 окт 2019 в 16:38
@andreymal, а, все, тупанул, сейчас поправлю)
5 окт 2019 в 16:39
Да и второй пример тоже просто не работает, потому что локальная переменная my_list перекроет глобальную, и глобальный список будет недоступен внутри функции
5 окт 2019 в 16:40
- python
- массивы
- функции
- return
-
Важное на Мете
Похожие
Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.1.8.3130
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
Как передать массив в функцию в Python?
Массив — это объект, его можно передать в функцию как и любой другой объект (число, строку и т.д.) в качестве аргумента.
# можно передать напрямую print([1, 2, 3, 4]) # [1, 2, 3, 4] # можно после присваивания переменной fruits = ['apple', 'banana', 'orange'] print(fruits) # ['apple', 'banana', 'orange']
Модуль array. Массивы в python

Модуль array определяет массивы в python. Массивы очень похожи на списки, но с ограничением на тип данных и размер каждого элемента.
Размер и тип элемента в массиве определяется при его создании и может принимать следующие значения:
| Код типа | Тип в C | Тип в python | Минимальный размер в байтах |
|---|---|---|---|
| ‘b’ | signed char | int | 1 |
| ‘B’ | unsigned char | int | 1 |
| ‘h’ | signed short | int | 2 |
| ‘H’ | unsigned short | int | 2 |
| ‘i’ | signed int | int | 2 |
| ‘I’ | unsigned int | int | 2 |
| ‘l’ | signed long | int | 4 |
| ‘L’ | unsigned long | int | 4 |
| ‘q’ | signed long long | int | 8 |
| ‘Q’ | unsigned long long | int | 8 |
| ‘f’ | float | float | 4 |
| ‘d’ | double | float | 8 |
Класс array.array(TypeCode [, инициализатор]) — новый массив, элементы которого ограничены TypeCode, и инициализатор, который должен быть списком, объектом, который поддерживает интерфейс буфера, или итерируемый объект.
array.typecodes — строка, содержащая все возможные типы в массиве.
Массивы изменяемы. Массивы поддерживают все списковые методы (индексация, срезы, умножения, итерации), и другие методы.
Методы массивов (array) в python
array.typecode — TypeCode символ, использованный при создании массива.
array.itemsize — размер в байтах одного элемента в массиве.
array.append(х) — добавление элемента в конец массива.
array.buffer_info() — кортеж (ячейка памяти, длина). Полезно для низкоуровневых операций.
array.byteswap() — изменить порядок следования байтов в каждом элементе массива. Полезно при чтении данных из файла, написанного на машине с другим порядком байтов.
array.count(х) — возвращает количество вхождений х в массив.
array.extend(iter) — добавление элементов из объекта в массив.
array.frombytes(b) — делает массив array из массива байт. Количество байт должно быть кратно размеру одного элемента в массиве.
array.fromfile(F, N) — читает N элементов из файла и добавляет их в конец массива. Файл должен быть открыт на бинарное чтение. Если доступно меньше N элементов, генерируется исключение EOFError , но элементы, которые были доступны, добавляются в массив.
array.fromlist(список) — добавление элементов из списка.
array.index(х) — номер первого вхождения x в массив.
array.insert(n, х) — включить новый пункт со значением х в массиве перед номером n. Отрицательные значения рассматриваются относительно конца массива.
array.pop(i) — удаляет i-ый элемент из массива и возвращает его. По умолчанию удаляется последний элемент.
array.remove(х) — удалить первое вхождение х из массива.
array.reverse() — обратный порядок элементов в массиве.
array.tobytes() — преобразование к байтам.
array.tofile(f) — запись массива в открытый файл.
array.tolist() — преобразование массива в список.
Вот и всё, что можно было рассказать про массивы. Они используются редко, когда нужно достичь высокой скорости работы. В остальных случаях массивы можно заменить другими типами данных: списками, кортежами, строками.
Для вставки кода на Python в комментарий заключайте его в теги