如何使用ctypes将数组从C++函数返回到Python

dol*_*lby 22 c++ python arrays ctypes return

我正在使用ctypes在Python中实现C++函数.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;
}
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

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

g++ -c -fPIC function.cpp -o function.o
g++ -shared -Wl,-soname,library.so -o library.so function.o
Run Code Online (Sandbox Code Playgroud)

你有什么建议我在Python中访问数组值吗?

Hui*_*eng 21

您的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]
Run Code Online (Sandbox Code Playgroud)

基本上有两个变化:

  1. 删除与numpy相关的代码并ctypes.cast调用,因为我们不需要它们.

  2. 指定返回类型ctypes.POINTER(ctypes.c_int * 10).

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

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

  • 你能指出我们如何在python中创建这样一个数组并将它的指针传递给C? (7认同)

Dou*_*gal 17

function.cpp返回一个int数组,同时wrapper.py尝试将它们解释为双精度数.更改ArrayTypectypes.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()
Run Code Online (Sandbox Code Playgroud)

  • 这里有一点巫术......当你完成它时你会如何删除内存? (2认同)
  • @XapaJlaMnu你的库应该有一个相应的`extern C`函数来调用释放内存,如果用`new`分配它,它在内部使用C++`delete`.ctypes使用C接口,因为C没有`delete`,所以ctypes也没有. (2认同)
  • 正如另一个答案所建议的那样,如果可能的话,通常最好用numpy分配内存,然后将其传递给C函数进行填充。 (2认同)