I'm looking forward to pass an Python-Object to an Boost Python Class. This Object has an ndarray as attribute and I want to store this ndarray as a private member variable in this Class to use it later on. I could'n find a proper way to do this and I get Compiler Errors when declaring a boost::python::numpy::ndarray variable as private.
Here is my current code:
#include <boost/python/numpy.hpp>
#include <boost/python.hpp>
namespace p = boost::python;
namespace np = boost::python::numpy;
class FlatlandCBS {
public:
FlatlandCBS(p::object railEnv) : m_railEnv(railEnv) {
// This is the Code I want to execute, so the ndarray is stored in the member varibale
p::object distance_map = p::extract<p::object>(railEnv.attr("distance_map"));
// Just a function which returns a ndarray (not the error)
map = p::extract<np::ndarray>(distance_map.attr("get")());
}
private:
p::object m_railEnv;
// Can't use this and I get a Compiler Error
np::ndarray map;
};
BOOST_PYTHON_MODULE(libFlatlandCBS) {
Py_Initialize();
np::initialize();
using namespace boost::python;
class_<FlatlandCBS>("FlatlandCBS", init<object>());
}
The resulting Error message is:
error: no matching function for call to ‘boost::python::numpy::ndarray::ndarray()’
Here is also my CMakeLists.txt so you may reproduce this error:
cmake_minimum_required (VERSION 3.8)
project (libFlatlandCBS)
# Add all the files to the library so it can get created
ADD_LIBRARY(FlatlandCBS SHARED
main.cpp)
# Set the Flags and the CXX command
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -fconcepts")
INCLUDE_DIRECTORIES(include)
set(boostPython python)
find_package(PythonInterp 3.6 REQUIRED)
find_package(PythonLibs 3.6 REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS})
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
FIND_PACKAGE(Boost REQUIRED COMPONENTS system program_options numpy ${boostPython})
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries(FlatlandCBS ${Boost_LIBRARIES} ${PYTHON_LIBRARIES})
else()
message(FATAL_ERROR "Could not find boost.")
endif()
The problem is that your constructor for FlatlandCBS
is invalid. As per cppreference :
Before the compound statement that forms the function body of the constructor begins executing, initialization of all direct bases, virtual bases, and non-static data members is finished. Member initializer list is the place where non-default initialization of these objects can be specified.
The error you get - error: no matching function for call to 'boost::python::numpy::ndarray::ndarray()'
- is the compiler telling you it has tried to use the default constructor of ndarray.This class doesn't have a default constructor, so you need to specify a different constructor to use in the initializer list (just like you did for m_railEnv
.). The simplest solution here would be to move map
's initialization into the initializer list like this:
FlatlandCBS(p::object railEnv) :
m_railEnv(railEnv),
map(
p::extract<np::ndarray>(
p::extract<p::object>(
railEnv.attr("distance_map")
).attr("get")()
)
)
{ }
It ain't the prettiest code, but it should work.
So with the help from @unddoch it was finally possible to solve this problem. It turned out that it is not possible to use two extraxt functions in a row, but somehow the following is possible:
FlatlandCBS(p::object railEnv) :
m_railEnv(railEnv),
m_map(
p::extract<np::ndarray>(
railEnv
.attr("distance_map")
.attr("get")()
)
)
So if you want to extraxt multible values form the python object, just do as many .atrr()
in a row.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.