c++ python arrays return ctypes

Cómo devolver un array desde la función C++ a Python usando ctypes



arrays return (2)

Estoy usando ctypes para implementar una función de C ++ en Python. La función C ++ debe devolver un puntero a una matriz. Desafortunadamente, no he descubierto cómo acceder a la matriz en Python. Intenté numpy.frombuffer, pero eso no tuvo éxito. Acaba de devolver una serie de números arbitrarios. Obviamente no lo usé correctamente. Aquí hay un ejemplo simple con una matriz de tamaño 10:

Contenido de function.cpp:

extern "C" int* function(){ int* information = new int[10]; for(int k=0;k<10;k++){ information[k] = k; } return information; }

Contenido de 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)

Para compilar el archivo C ++ que estoy usando:

g++ -c -fPIC function.cpp -o function.o g++ -shared -Wl,-soname,library.so -o library.so function.o

¿Tiene alguna sugerencia sobre qué debo hacer para acceder a los valores de matriz en Python?


Tu código de Python funcionará después de algunas modificaciones menores:

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]

Básicamente hay dos cambios:

  1. elimine el código relacionado con ctypes.cast y la llamada a ctypes.cast ya que no los necesitamos.

  2. especifique el tipo de retorno a ctypes.POINTER(ctypes.c_int * 10) .

    Por defecto, se asume que las funciones externas devuelven el tipo C int, por lo tanto, necesitamos cambiarlo al tipo de puntero deseado.

Por cierto, devolver una matriz ed new de código C a código Python parece inapropiado. ¿Quién y cuándo liberará la memoria? Es mejor crear matrices en código Python y pasarlas al código C. De esta manera queda claro que el código Python es el propietario de los arreglos y asume la responsabilidad de crear y reclamar sus espacios.


function.cpp devuelve una matriz int, mientras que wrapper.py intenta interpretarlos como dobles. Cambie ArrayType a ctypes.c_int * 10 y debería funcionar.

Es probable que sea más fácil usar np.ctypeslib lugar de hacerlo desde frombuffer . Esto debería parecer algo como

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()