Вопрос по c++, arrays, ctypes, return, python – Как вернуть массив из функции C ++ в Python, используя ctypes

19

Я использую ctypes для реализации функции C ++ в Python. Функция C ++ должна возвращать указатель на массив. К сожалению я неЯ понял, как получить доступ к массиву в Python. Я попытался numpy.frombuffer, но это не удалось. Он просто вернул массив произвольных чисел. Очевидно, я неЯ использовал это правильно. Вот простой пример с массивом размером 10:

Содержание function.cpp:

extern "C" int* function(){
int* information = new int[10];
for(int k=0;k
Конечно, я забыл импортировать некоторые специфические функции ctypes, такие как c_double и POINTER. Я просто забыл добавить их здесь. dolby

Ваш Ответ

2   ответа
15

function.cpp возвращает массив int, аwrapper.py пытается интерпретировать их как двойники. + ИзменитьArrayType вctypes.c_int * 10 и это должно работать.

Это'вероятно, проще использоватьnp.ctypeslib вместоfrombuffer сам. Это должно выглядеть примерно так

import ctypes
from numpy.ctypeslib import ndpointer

lib = ctypes.CDLL('./library.so')
lib.function.restype = ndpointer(dtype=ctypes.c_int, shape=(10,))

res = lib.function()
Отлично, большое спасибо! Это работает сейчас. Python просто дает мне предупреждение[...] RuntimeWarning: Неверная строка формата PEP 3118: '<P' [...]» Но согласноэто обсуждение это не проблема. dolby
Я также импортировал c_int и заменил c_double, но python теперь печатает массив только из 5 элементов, а значения по-прежнему неверны. Это странно dolby
Немного некромантии здесь ... Как бы вы удалили память, когда сделали с ней? XapaJIaMnu
Как предлагается в другом ответе, если это возможноОбычно лучше выделить память с помощью numpy и передать ее функции C для заполнения. Dougal
@XapaJlaMnu Ваша библиотека должна иметь соответствующийextern C функция для вызова памяти, которая внутренне использует C ++delete если он был наделенnew, ctypes использует интерфейсы C, а поскольку C неиметьdeleteтакже как и ctypes. Dougal
19

import ctypes

f = ctypes.CDLL('./library.so').function
f.restype = ctypes.POINTER(ctypes.c_int * 10)
print [i for i in f().contents] # output: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

В основном есть два изменения:

удалить код, связанный с NumPy иctypes.cast позвони, так как мы неони не нужны.

укажите тип возвращаемого значения.ctypes.POINTER(ctypes.c_int * 10)

По умолчанию предполагается, что внешние функции возвращают тип C int, поэтому нам нужно изменить его на нужный тип указателя.

Кстати, возвращаяnewМассив ed из кода C в код Python кажется неуместным. Кто и когда освободит память? Это'Лучше создавать массивы в коде Python и передавать их в C-код. Вот такясно, что код Pythonвладеет массивы и берет на себя ответственность за создание и восстановление их пространства.

Можете ли вы указать, как бы мы создали такой массив в Python и передали его?указатель на C? shahensha
Немного некромантии здесь ... Как бы вы удалили память, когда сделали с ней? XapaJIaMnu
@Shahensha То, что я делаю для массивов int / float, - это использование numpy массивов и встроенного интерфейса ctypes ()data_as Adversus

Похожие вопросы