在C ++中嵌入python/numpy [英] Embed python / numpy in C++

查看:101
本文介绍了在C ++中嵌入python/numpy的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在我的C ++应用程序中使用python 3(带numpy).这需要将C ++数组发送到python,执行计算,然后在C ++中检索结果.为此,我基于这里讨论的代码: https://codereview.stackexchange.com/Questions/92266/send-ac-array-to-python-numpy-and-back/92353#92353 还有这里:将C ++数组发送到Python并返回(扩展带有Numpy的C ++).

I am trying to use python 3 (with numpy) in my C++ application. This entails sending a C++ array to python, performing calculations and then retrieving the result in C++. To do this I based myself on the code that was discussed here: https://codereview.stackexchange.com/questions/92266/sending-a-c-array-to-python-numpy-and-back/92353#92353 and also here: Sending a C++ array to Python and back (Extending C++ with Numpy).

虽然代码复查示例中的示例基本可行,但是当我修改python和C ++脚本时,返回值遇到了麻烦:当我尝试返回在python中创建的变量时,结果是nan的向量而不是预期的计算.我的猜测是该对象某种程度上超出了范围,但我无法解决此问题.

While the example from the code review post basically works I am having troubles with the return values when I modified the python and C++ script: when I am trying to return a variable that was created in python the result is a vector of nan instead of the intended computations. My guess is that the object somehow goes out of scope but I can't fix this problem.

我在名为 mymodule.py 的文件中使用以下python脚本:

I use the following python script in a file called mymodule.py:

import numpy

def array_tutorial(a):
    print("array_tutorial - python")
    print(a)
    print("")
    firstRow = a[0,:]
    #beta = numpy.array([[10,20,30],[10,20,30],[10,20,30]])
    #firstRow = beta[0,:]
    return firstRow

def myfunction():
    beta = numpy.array([[1,2,3],[1,2,3],[1,2,3]])
    print("myfunction - python")
    print(beta)
    print("")
    firstRow = beta[0,:]
    return firstRow

我的C ++代码位于文件 numpy_cpp.cpp 中,该文件是对代码查看帖子的可接受答案的稍作更改和简化的版本.

My C++ code is in the file numpy_cpp.cpp which is a slightly changed and simplified version of the accepted answer to the code review post.

#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION

#include <stdio.h>
#include <iostream>
#include <stdlib.h> 

#include <Python.h>
#include "numpy/arrayobject.h"

int main(int argc, char* argv[])
{
    setenv("PYTHONPATH", ".", 0);

    Py_Initialize();
    import_array();

    // Build the 2D array in C++
    const int SIZE = 3;
    npy_intp dims[2]{SIZE, SIZE};
    const int ND = 2;
    long double(*c_arr)[SIZE]{ new long double[SIZE][SIZE] };

    for (int i = 0; i < SIZE; i++){
        for (int j = 0; j < SIZE; j++){
            c_arr[i][j] = i + j;}
    }

    // Convert it to a NumPy array.
    PyObject *pArray = PyArray_SimpleNewFromData(ND, dims, NPY_LONGDOUBLE, reinterpret_cast<void*>(c_arr));

    // import mymodule
    const char *module_name = "mymodule";
    PyObject *pName = PyUnicode_FromString(module_name);
    PyObject *pModule = PyImport_Import(pName);
    Py_DECREF(pName);

    // import function
    const char *func_name = "array_tutorial";
    PyObject *pFunc = PyObject_GetAttrString(pModule, func_name);
    PyObject *pReturn = PyObject_CallFunctionObjArgs(pFunc, pArray, NULL);
    PyArrayObject *np_ret = reinterpret_cast<PyArrayObject*>(pReturn);

    // Convert back to C++ array and print.
    int len = PyArray_SHAPE(np_ret)[0];
    long double* c_out;
    c_out = reinterpret_cast<long double*>(PyArray_DATA(np_ret));
    std::cout << "Printing output array - C++" << std::endl;
    for (int i = 0; i < len; i++){
        std::cout << c_out[i] << ' ';
    }
    std::cout << std::endl << std::endl;


    // import function without arguments
    const char *func_name2 = "myfunction";
    PyObject *pFunc2 = PyObject_GetAttrString(pModule, func_name2);
    PyObject *pReturn2 = PyObject_CallFunctionObjArgs(pFunc2, NULL);
    PyArrayObject *np_ret2 = reinterpret_cast<PyArrayObject*>(pReturn2);

    // convert back to C++ array and print
    int len2 = PyArray_SHAPE(np_ret2)[0];
    long double* c_out2;
    c_out2 = reinterpret_cast<long double*>(PyArray_DATA(np_ret2));
    std::cout << "Printing output array 2 - C++" << std::endl;
    for (int i = 0; i < len2; i++){
        std::cout << c_out2[i] << ' ';
    }
    std::cout << std::endl << std::endl;

    Py_Finalize();
    return 0;
}

与我必须添加的接受答案相比

Compared to the accepted answer I had to add

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

为确保找到python脚本,我为没有输入参数的函数"myfunction"添加了第二个函数调用,并删除了一些错误处理.

to make sure the python script is found, I added the second function call for the function "myfunction" that has no input arguments and I removed some of the error handling.

我在Ubuntu 16.10上并使用

I am on Ubuntu 16.10 and and use

g++ -Wall numpy_cpp.cpp -I/usr/include/python3.5m/ -lpython3.5m  

进行编译和链接(除import_array()发出一条警告外,其他方法均正常).我的目标是python 3.

to compile and link (which goes fine except for one warning by import_array()). I am targeting python 3.

但是运行该程序会提供以下控制台输出:

Running the program however gives the following console output:

array_tutorial - python
[[ 0.0  1.0  2.0]
 [ 1.0  2.0  3.0]
 [ 2.0  3.0  4.0]]

Printing output array - C++
0 1 2 

myfunction - python
[[1 2 3]
 [1 2 3]
 [1 2 3]]

Printing output array 2 - C++
nan nan nan 

这是给我带来麻烦的最后一个输出,其中python返回在python脚本中设置的numpy数组的第一行.从python打印语句看来,numpy数组很好(不是nan),但是一旦将其引用到C ++,事情就会发生变化.

It is the last output that gives me trouble, where python returns the first row of an numpy array that was set up in the python script. From the python print statements it seems that the numpy array is fine (not nan), but once it is referred to C++ things go sideways.

如果我取消注释array_tutorial函数中return语句上方的两行,则对于第一个函数调用,我得到的结果相同(令人失望).

If I uncomment the two lines above the return statement in the array_tutorial function I get the same (disappointing) result for the first function call.

因此,我的问题是如何在C ++中获取正确的值而又不使对象(可能)超出范围?

My question is therefore how to get the correct values in C++ without the objects going (presumably) out of scope?

对于冗长的帖子,我深表歉意,在此先感谢您的帮助!

I apologize for the lengthy post, and thank you in advance for any help!

编辑:正如lomereiter指出的那样,应在python中设置numpy数组时牢记数据类型.这样就解决了问题.更好的python脚本可以输出以下内容:

As pointed out by lomereiter below the numpy arrays in python should be set up keeping the data types in mind. This solves the problem. A better python script that outputs the data type of the received array and specifies the data type of the declared array would be:

import numpy

def array_tutorial(a):
    print("array_tutorial - python")
    print(a)
    print(numpy.dtype(a[0,0]))
    print("")
    firstRow = a[0,:]
    #beta = numpy.array([[10,20,30],[10,20,30],[10,20,30]],dtype=numpy.float128)
    #firstRow = beta[0,:]
    return firstRow

def myfunction():
    beta = numpy.array([[1,2,3],[1,2,3],[1,2,3]],dtype=numpy.float128)
    print("myfunction - python")
    print(beta)
    print("")
    firstRow = beta[0,:]
    return firstRow

推荐答案

在Python代码中创建数组时,应指定dtype.dtype被推断为int64(在64位平台上)时,您正在C ++代码中转换为long double.

You should specify dtype when you create the array in Python code. You are casting to long double in C++ code while the dtype is deduced to be int64 (on 64-bit platforms)

这篇关于在C ++中嵌入python/numpy的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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