Перейти к содержимому

Как передать массив в функцию python

  • автор:

Python-сообщество

[RSS Feed]

  • Начало
  • » 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

Python 3 логотип

Модуль 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 в комментарий заключайте его в теги

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *