Я использую ctypes для реализации функции C ++ в Python. Функция C ++ должна возвращать указатель на массив. К сожалению, я не понял, как получить доступ к массиву в Python. Я попытался numpy.frombuffer, но это не удалось. Он просто возвратил массив произвольных чисел. Очевидно, я не использовал это правильно. Вот простой пример с массивом размером 10:
Содержание function.cpp:
extern "C" int* function(){
int* information = new int[10];
for(int k=0;k<10;k++){
information[k] = k;
}
return information;
}
Содержание wrapper.py:
import ctypes
import numpy as np
output = ctypes.CDLL('./library.so').function()
ArrayType = ctypes.c_double*10
array_pointer = ctypes.cast(output, ctypes.POINTER(ArrayType))
print np.frombuffer(array_pointer.contents)
Для компиляции файла C ++ я использую:
g++ -c -fPIC function.cpp -o function.o
g++ -shared -Wl,-soname,library.so -o library.so function.o
Есть ли у вас какие-либо предложения, что мне нужно сделать, чтобы получить доступ к значениям массива в Python?
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 будет работать после некоторых незначительных изменений:
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 владеет массивы и берет на себя ответственность за создание и восстановление их пространства.