2

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()

2 Answers 2

1

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.

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

Comments

1

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.

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.