1

I followed the tutorial on boost::python::numpy, found that numpy's ndarray and array could be shared inside C ++ code, and I found that using the Boost python example, I could call a python function in C ++ with arguments and return.

My goal is that boost python and python exchange numpy array values.

First, I tried to pass the numpy array to the python code with boost python. However, I only found a way to set the pylist to PyList_SET_ITEM by creating a pylist instead of a numpy array.

In C++

//https://docs.python.org/2.0/ext/buildValue.html
PyObject *Convert_Big_Array(long arr[], int length) {
    PyObject *pylist, *item;
    pylist = PyList_New(length);
    if (pylist != NULL) 
        for (int i = 0; i < length; i++) {
            item = PyLong_FromLong(arr[i]);
            PyList_SET_ITEM(pylist, i, item);
        }
    return pylist;
}


int main() {
    long arr[5] = { 4,3,2,6,10 };
    // Python 3.x Version   
    Py_SetPythonHome(L"C:\\Users\\User\\Anaconda3");
    PyObject *pName, *pModule, *pDict, *pFunc, *pValue, *presult;
    Py_Initialize();

        return 0;
    }
    pDict = PyModule_GetDict(pModule);
    pFunc = PyDict_GetItemString(pDict, (char*)"someFunction");
    if (PyCallable_Check(pFunc)) {
        pValue = Py_BuildValue("(O)", Convert_Big_Array(arr, 5));
        PyErr_Print();
        presult = PyObject_CallObject(pFunc, pValue);
        PyErr_Print();
    }
    else {
        PyErr_Print();
        return 0;
    }
    boost::python::handle<> handle(presult);
    std::cout << std::endl << "Python ndarray :" << p::extract<char const *>(p::str(handle)) << std::endl;
    Py_DECREF(pValue);
    Py_DECREF(pModule);
    Py_DECREF(pName);
    Py_Finalize();
    return 0;

}

In Python

import numpy as np

def someFunction(text):
    print(text)
    return np.array([1,2,3])

With this code I find it very difficult to pass a very large C int array to Python. Is there a more efficient way?

First, if I can convert a C ++ array to ndarray using np :: from_data and then convert it to PyObject, I think I can pass this object itself to python.

Second, I want to convert PyObject (presult) created with PyObject_CallObject to np :: ndarray format. Now the code is just an example and the output is successful.

In other words, do you know how to convert ndarray (C ++) -> PyObject (C ++), PyObject (numpy c ++) -> ndarray (c ++)?

1 Answer 1

0

I got a answer, and post Here for others...

thank you.

//#include <Python.h>
#include <stdlib.h>
#include <boost/python/numpy.hpp>
#include <boost/python.hpp>
#include <iostream>

//
////#define BOOST_PYTHON_STATIC_LIB
//
using namespace boost::python;
namespace np = boost::python::numpy;



//https://stackoverflow.com/questions/10701514/how-to-return-numpy-array-from-boostpython/14232897#14232897
np::ndarray mywrapper() {
    std::vector<short> v;
    v.push_back(3);
    v.push_back(5);
    Py_intptr_t shape[1] = { v.size() };
    np::ndarray result = np::zeros(1, shape, np::dtype::get_builtin<short>());
    std::copy(v.begin(), v.end(), reinterpret_cast<short*>(result.get_data()));
    //std::cout <<"C++ Memory Addr : " << std::dec << &result << std::endl;
    return result;
}


//https://stackoverflow.com/questions/54904448/boost-python-nullptr-while-extracting-ndarray
int main() {
    double t_end = 7;
    long arr[5] = { 4,3,2,6,10 };
    // Python 3.x Version   
    Py_SetPythonHome(L"C:\\Users\\YangwooKim\\Anaconda3");
    //PyObject *pName, *pModule, *pDict, *pFunc, *pValue, *presult;
    Py_Initialize();
    np::initialize();

    object module = import("__main__");
    object name_space = module.attr("__dict__");
    exec_file("arbName.py", name_space, name_space);

    object MyFunc = name_space["someFunction"];
    object result;
    //for(int i=0; i<1000000; i++)
        result = MyFunc(mywrapper());
    //printf("Result is %d\n", PyLong_AsLong(presult));
    //np::ndarray py_array = np::from_object(boost::python::object(handle));
    //auto k = extract<np::ndarray>();
    //np::ndarray k = np::from_object(object);
    //np::ndarray k = p::extract<np::ndarray>(object);
    //const np::ndarray& ret = k();
    auto result_array = extract<numpy::ndarray>(result);
    const numpy::ndarray& ret = result_array();
    int input_size = ret.shape(0);
    short* input_ptr = reinterpret_cast<short*>(ret.get_data());
    //std::cout << std::endl
    //  << "Python ndarray :" << p::extract<char const *>(p::str(object)) << std::endl;
    std::cout << std::endl << "Python ndarray :" << input_size << std::endl;
    for (int i = 0; i < input_size; ++i)
        std::cout <<" " <<*(input_ptr + i) <<std::endl;
    //Py_Finalize();
    //Py_Finalize();
    return 0;

}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.