use*_*486 12 c++ python arrays numpy cython
我有一些在Python中编写的代码,其输出是一个numpy数组,现在我想将该输出发送到C++代码,其中将执行大量的计算.
我尝试过使用cython public cdef,但我正在运行一些问题.非常感谢你的帮助!这是我的代码:
pymodule.pyx:
from pythonmodule import result # result is my numpy array
import numpy as np
cimport numpy as np
cimport cython
@cython.boundscheck(False)
@cython.wraparound(False)
cdef public void cfunc():
print 'I am in here!!!'
cdef np.ndarray[np.float64_t, ndim=2, mode='c'] res = result
print res
Run Code Online (Sandbox Code Playgroud)
一旦进行了cython化,我打电话给:
pymain.c:
#include <Python.h>
#include <numpy/arrayobject.h>
#include "pymodule.h"
int main() {
Py_Initialize();
initpymodule();
test(2);
Py_Finalize();
}
int test(int a)
{
Py_Initialize();
initpymodule();
cfunc();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我得到一个NameError为result以可变C++.我已经尝试用指针定义它并间接从其他函数调用它,但该数组仍然是不可见的.我很确定答案很简单,但我不明白.谢谢你的帮助!
NameError是因为Python无法找到模块,工作目录不会自动添加到您的PYTHONPATH.在代码中使用setenvwith 修复此问题.setenv("PYTHONPATH", ".", 1);C/C++
显然,有一种简单的方法可以做到这一点.使用pythonmodule.py包含已创建数组的python模块:
import numpy as np
result = np.arange(20, dtype=np.float).reshape((2, 10))
Run Code Online (Sandbox Code Playgroud)
您可以pymodule.pyx使用public关键字构建导出该数组的结构.通过添加一些辅助功能,您通常不需要触摸Python和Numpy C-API:
from pythonmodule import result
from libc.stdlib cimport malloc
import numpy as np
cimport numpy as np
cdef public np.ndarray getNPArray():
""" Return array from pythonmodule. """
return <np.ndarray>result
cdef public int getShape(np.ndarray arr, int shape):
""" Return Shape of the Array based on shape par value. """
return <int>arr.shape[1] if shape else <int>arr.shape[0]
cdef public void copyData(float *** dst, np.ndarray src):
""" Copy data from src numpy array to dst. """
cdef float **tmp
cdef int i, j, m = src.shape[0], n=src.shape[1];
# Allocate initial pointer
tmp = <float **>malloc(m * sizeof(float *))
if not tmp:
raise MemoryError()
# Allocate rows
for j in range(m):
tmp[j] = <float *>malloc(n * sizeof(float))
if not tmp[j]:
raise MemoryError()
# Copy numpy Array
for i in range(m):
for j in range(n):
tmp[i][j] = src[i, j]
# Assign pointer to dst
dst[0] = tmp
Run Code Online (Sandbox Code Playgroud)
函数getNPArray并分别getShape返回数组及其形状.copyData添加是为了只提取ndarray.data并复制它,这样你就可以完成Python并在没有初始化解释器的情况下工作.
示例程序(in C,C++应该看起来相同)看起来像这样:
#include <Python.h>
#include "numpy/arrayobject.h"
#include "pyxmod.h"
#include <stdio.h>
void printArray(float **arr, int m, int n);
void getArray(float ***arr, int * m, int * n);
int main(int argc, char **argv){
// Holds data and shapes.
float **data = NULL;
int m, n;
// Gets array and then prints it.
getArray(&data, &m, &n);
printArray(data, m, n);
return 0;
}
void getArray(float ***data, int * m, int * n){
// setenv is important, makes python find
// modules in working directory
setenv("PYTHONPATH", ".", 1);
// Initialize interpreter and module
Py_Initialize();
initpyxmod();
// Use Cython functions.
PyArrayObject *arr = getNPArray();
*m = getShape(arr, 0);
*n = getShape(arr, 1);
copyData(data, arr);
if (data == NULL){ //really redundant.
fprintf(stderr, "Data is NULL\n");
return ;
}
Py_DECREF(arr);
Py_Finalize();
}
void printArray(float **arr, int m, int n){
int i, j;
for(i=0; i < m; i++){
for(j=0; j < n; j++)
printf("%f ", arr[i][j]);
printf("\n");
}
}
Run Code Online (Sandbox Code Playgroud)
永远记得设置:
setenv("PYTHONPATH", ".", 1);
Run Code Online (Sandbox Code Playgroud)
在调用之前Py_Initialize,Python可以在工作目录中找到模块.
剩下的就是直截了当.它可能需要一些额外的错误检查,并且肯定需要一个函数来释放分配的memmory.
这样做你正在尝试的方法是这样的麻烦比它的价值,你可能会更好使用numpy.save,以节省您的阵列中的npy二进制文件,然后使用一些C++库,读取文件你.