xtensor-stack / xtensor-python

Python bindings for xtensor
BSD 3-Clause "New" or "Revised" License
345 stars 58 forks source link

Retrieving xt::pyarray when embedding python using pybind11 #282

Closed akapelrud closed 1 year ago

akapelrud commented 1 year ago

All of the examples show extending python with C++ but how can I translate from a numpy ndarray to a xt::pyarray when embedding python using pybind11?

Given: test.py:

import numpy as np

def generate_data():
    v = np.arange(15).reshape(3,5)
    return v

and the C++ source:

#define FORCE_IMPORT_ARRAY
#include <xtensor-python/pyarray.hpp>

#include <pybind11/embed.h>
namespace py = pybind11;

void someprocedure() {
    py::scoped_interpreter guard{};
    py::module_ test = py::module_::import("test"); // import local python module
    py::object result = test.attr("generate_data")(); // call function from python module

   // How can I retrieve an array from result?
   xt::pyarray<double> array0(result); // segfault
   xt::pyarray<double> array1 = result.cast<xt::pyarray<double>>(); // segfault
}
akapelrud commented 1 year ago

It was as simple as adding the xt::import_numpy(); call to the embedding scope.

#define FORCE_IMPORT_ARRAY
#include <xtensor-python/pyarray.hpp>

#include <pybind11/embed.h>
namespace py = pybind11;

void someprocedure() {
    py::scoped_interpreter guard{};

    xt::import_numpy();

    py::module_ test = py::module_::import("test"); // import local python module
    py::object result = test.attr("generate_data")(); // call function from python module

   // this now works as expected:
   xt::pyarray<double> array0(result);
   return 0;
}