如何使用ctype从c++函数返回数组到Python

时间:2021-07-23 02:01:07

I am using ctypes to implement a C++ function in Python. The C++ function should return a pointer to an array. Unfortunately I haven't figured out, how to access the array in Python. I tried numpy.frombuffer, but that was not successful. It just returned an array of arbitrary numbers. Obviously I didn't used it correctly. Here is a simple example with an array of size 10:

我正在使用ctypes来实现Python中的c++函数。函数应该返回一个指向数组的指针。不幸的是,我还没弄明白如何用Python来访问数组。我尝试过numpi .frombuffer,但没有成功。它只返回一个任意数的数组。显然我用错了。下面是一个数组大小为10的简单示例:

Content of function.cpp:

function.cpp内容:

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

Content of wrapper.py:

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)

To compile the C++ file i am using:

要编译我正在使用的c++文件:

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

Do you have any suggestions what I have to do to access the array values in Python?

您有什么建议吗?我该怎么做才能访问Python中的数组值?

2 个解决方案

#1


14  

function.cpp returns an int array, while wrapper.py tries to interpret them as doubles. Change ArrayType to ctypes.c_int * 10 and it should work.

函数。cpp返回一个int数组,而包装器。py试图把它们解释为双重性。ArrayType改为ctypes。c_int * 10,应该可以。


It's probably easier to just use np.ctypeslib instead of frombuffer yourself. This should look something like

使用np很容易。ctypeslib代替自己的buffer。应该是这样的

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

#2


19  

Your python code will work after some minor modifications:

您的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]

Basically there are two changes:

基本上有两个变化:

  1. remove numpy-related code and ctypes.cast call since we don't need them.

    删除与numpy相关的代码和ctype。因为我们不需要他们。

  2. specify the return type to ctypes.POINTER(ctypes.c_int * 10).

    指定ctypes. pointer (ctypes)的返回类型。c_int * 10)。

    By default foreign functions are assumed to return the C int type, hence we need change it to the desired pointer type.

    默认情况下,我们假定外函数返回C int类型,因此我们需要将它更改为所需的指针类型。

BTW, returning a newed array from C code to Python code seems inappropriate. Who and when will free the memory? It's better to create arrays in Python code and pass them to C code. This way it's clear that the Python code owns the arrays and takes the responsibility of creating and reclaiming their spaces.

顺便说一句,从C代码返回一个新的数组到Python代码似乎不合适。谁和什么时候会释放记忆?最好在Python代码中创建数组并将其传递给C代码。这样,很明显,Python代码拥有数组,并负责创建和回收它们的空间。

#1


14  

function.cpp returns an int array, while wrapper.py tries to interpret them as doubles. Change ArrayType to ctypes.c_int * 10 and it should work.

函数。cpp返回一个int数组,而包装器。py试图把它们解释为双重性。ArrayType改为ctypes。c_int * 10,应该可以。


It's probably easier to just use np.ctypeslib instead of frombuffer yourself. This should look something like

使用np很容易。ctypeslib代替自己的buffer。应该是这样的

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

#2


19  

Your python code will work after some minor modifications:

您的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]

Basically there are two changes:

基本上有两个变化:

  1. remove numpy-related code and ctypes.cast call since we don't need them.

    删除与numpy相关的代码和ctype。因为我们不需要他们。

  2. specify the return type to ctypes.POINTER(ctypes.c_int * 10).

    指定ctypes. pointer (ctypes)的返回类型。c_int * 10)。

    By default foreign functions are assumed to return the C int type, hence we need change it to the desired pointer type.

    默认情况下,我们假定外函数返回C int类型,因此我们需要将它更改为所需的指针类型。

BTW, returning a newed array from C code to Python code seems inappropriate. Who and when will free the memory? It's better to create arrays in Python code and pass them to C code. This way it's clear that the Python code owns the arrays and takes the responsibility of creating and reclaiming their spaces.

顺便说一句,从C代码返回一个新的数组到Python代码似乎不合适。谁和什么时候会释放记忆?最好在Python代码中创建数组并将其传递给C代码。这样,很明显,Python代码拥有数组,并负责创建和回收它们的空间。