28

我正在使用 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;
}

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 中的数组值?

4

2 回答 2

25

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

基本上有两个变化:

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

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

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

顺便说一句,将newed 数组从 C 代码返回到 Python 代码似乎不合适。谁以及何时释放内存?最好在 Python 代码中创建数组并将它们传递给 C 代码。这样,很明显 Python 代码拥有数组并负责创建和回收它们的空间。

于 2013-02-15T10:45:28.277 回答
24

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()
于 2013-02-15T02:56:40.630 回答