如何将C ++向量转换为numpy数组或如何在C ++,Cython和Python之间来回移动向量指针?

时间:2015-02-27 07:04:55

标签: python c++ numpy vector cython

问题是,我有一个C ++向量,需要将其转换为numpy数组。载体来自外部库。我可以做的就是在源中添加一个额外的函数,然后再将它重新编译为原始的DLL。我的想法是,我用ctypes导入函数,然后用void指针指针调用它,让C ++函数插入向量指针。 这里开始了第一个问题。我只能通过显式分配内存将指针发送回Python。我不仅需要使用

myVec = new vector<T>

即使是我需要使用

的int指针
myIntP = new int

简单地做

x = 10
int* myIntP = &x
*pythonIntPP = myIntP

不起作用。回到Python,我仍然会有原始指针。

**pythonIntPP = x
不过,

会奏效。

为什么我必须为指针分配内存?

无论如何,让我们找到我发现的解决方案: 首先,你将在一个接受void **的DLL中拥有一个C ++函数。 在Python中做

from ctypes import *
lib = cdll.LoadLibrary(r"C:\path\to.dll")
gvp = lib.GetVectorPointer
gvp.restype = c_int
gvp.argtypes = [POINTER(c_void_p), POINTER(c_int)] # we need the vector pointer and size
voidPP = pointer(c_void_p())
sizeP = pointer(c_int())
gvp(voidPP, sizeP)

现在我们在Python对象中有向量指针和大小,但我们无法在Cython中解包指针。因此,我们需要创建一个cdef函数,将其导出到DLL(pyd文件)中,然后再在Python中导入它。

在Cython中我们做

import numpy as np
cimport numpy as np

from libcpp.vector cimport vector

ctypedef vector[T] Vec
ctypedef myVec* VecP
ctypedef VecP* VecPP

arr = np.empty(1, dtype=np.uint8)

def allocate_arr(size):
    arr.resize(size, refcheck=False)

cdef public int vec_to_numpy(void** voidPP):
    cdef VecP vecp= <VecP>ppVoid[0]
    cdef int size = vecp[0].size()
    cdef np.ndarray[T, ndim=1] data = arr # arr needs to be allocated 
    cdef int i
    for i in range(size):
        data[i] = vecp[0][i]

    return 0

在Python中,我们现在可以调用此函数并获取数组

lib = windll.LoadLibrary(r"C:\path\to\module.pyd")
v2n = lib.vec_to_numpy
v2n.restype = c_int
v2n.argtypes = [POINTER(c_void_p)]
import module
module.allocate_arr(sizeP) # allocate first
v2n(voidPP) # send the vector pointer to the Cython function

module.arr # this is the numpy array with the vector data

提示: 您可以告诉链接器使用两个hack之一导出您的Cython函数。 在代码的开头为每个要导出的函数写下这一行(相应地更改名称)。

cdef void emit_pragma 'foo ();\n#pragma comment(linker, "/export:vec_to_numpy=vec_to_numpy")\nstatic void unused' ():pass

或在函数定义中使用此hack(使用__stdcall以避免名称损坏)。

cdef int vec_to_numpy 'unused;\nextern "C" __declspec(dllexport)  public int __stdcall vec_to_numpy' (void** voidPP):

您是否了解在这三种语言之间获得充分灵活性的更好方法?

是否有更简单的方法来导出符号,以便可以将它们导入到不涉及黑客攻击的Python中?能够直接在Python中使用cdef函数对我来说非常方便。

0 个答案:

没有答案