将numpy数组传递给C ++ [英] Passing a numpy array to C++

查看:97
本文介绍了将numpy数组传递给C ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些用Python写的代码,其输出是一个numpy数组,现在我想将该输出发送到 C ++ 代码,其中将执行大部分计算.

I have some code writen in Python for which the output is a numpy array, and now I want to send that output to C++ code, where the heavy part of the calculations will be performed.

我曾尝试使用cython的 public cdef ,但是我在某些问题上运行.多谢您的协助!这是我的代码:

I have tried using cython's public cdef, but I am running on some issues. I would appreciate your help! Here goes my code:

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

一旦被cythonized,我会打电话给

Once this is cythonized, I call:

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;
}

我在 C ++ 处得到 result 变量的 NameError .我尝试使用指针定义它并从其他函数间接调用它,但是数组仍然不可见.我很确定答案很简单,但我只是不明白.感谢您的帮助!

I am getting a NameError for the result variable at C++. I have tried defining it with pointers and calling it indirectly from other functions, but the array remains invisible. I am pretty sure the answer is quite simple, but I just do not get it. Thanks for your help!

推荐答案

简短回答

NameError是由于Python找不到模块而导致的,因此工作目录不会自动添加到您的 setenv C/C ++ 代码中的 setenv("PYTHONPATH",.",1); 一起解决.

Short Answer

The NameError was cause by the fact that Python couldn't find the module, the working directory isn't automatically added to your PYTHONPATH. Using setenv with setenv("PYTHONPATH", ".", 1); in your C/C++ code fixes this.

显然,有一种简单的方法可以做到这一点.使用包含已创建数组的python模块 pythonmodule.py :

There's an easy way to do this, apparently. With a python module pythonmodule.py containing an already created array:

import numpy as np

result = np.arange(20, dtype=np.float).reshape((2, 10))

您可以使用

You can structure your pymodule.pyx to export that array by using the public keyword. By adding some auxiliary functions, you'll generally won't need to touch neither the Python, nor the 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

函数 getNPArray getShape 分别返回数组及其形状.添加了 copyData 以便提取

Function getNPArray and getShape return the array and its shape, respectively. copyData was added in order to just extract the ndarray.data and copy it so you can then finalize Python and work without having the interpreter initialized.

一个示例程序(在 C 中, C ++ 应该看起来完全相同)看起来像这样:

A sample program (in C, C++ should look identical) would look like this:

#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");
    }
}

始终记得设置:

setenv("PYTHONPATH", ".", 1);

之前,您调用 Py_Initialize ,以便Python可以在工作目录中找到模块.

before you call Py_Initialize so Python can find modules in the working directory.

其余的非常简单.它可能需要进行一些其他的错误检查,并且一定需要一个函数来释放分配的内存.

The rest is pretty straight-forward. It might need some additional error-checking and definitely needs a function to free the allocated memmory.

以您尝试的方式进行操作很麻烦,而不是值得的,使用 为您读取该文件的C ++库 .

Doing it the way you are attempting is way hassle than it's worth, you would probably be better off using numpy.save to save your array in a npy binary file and then use some C++ library that reads that file for you.

这篇关于将numpy数组传递给C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆