Использование Boost для обмена Python и C Numpy Array - PullRequest
0 голосов
/ 24 июня 2019

Я следовал руководству по boost :: python :: numpy, обнаружил, что ndarray и массив numpy могут быть общими внутри кода C ++, и обнаружил, что с помощью примера Python Boost я могу вызвать функцию python в C ++ с аргументами и возвратом.

Моя цель состоит в том, чтобы boost python и python обменивались значениями numpy массивов.

Сначала я попытался передать numpy массив в код python с помощью boost python.Однако я нашел способ установить для pylist значение PyList_SET_ITEM только путем создания pylist вместо массива numpy.

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

}

В Python

import numpy as np

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

С этим кодом мне очень трудно передать очень большой массив C int в Python.Есть ли более эффективный способ?

Во-первых, если я могу преобразовать массив C ++ в ndarray, используя np :: from_data, а затем преобразовать его в PyObject, я думаю, что я могу передать сам этот объект в python.

Во-вторых, я хочу преобразовать PyObject (presult), созданный с помощью PyObject_CallObject, в формат np :: ndarray.Теперь код является только примером, и вывод успешен.

Другими словами, знаете ли вы, как конвертировать ndarray (C ++) -> PyObject (C ++), PyObject (numpy c ++)) -> ndarray (c ++)?

1 Ответ

0 голосов
/ 25 июня 2019

Я получил ответ, и пост здесь для других ...

спасибо.

//#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;

}
...