使用boostpythonnumpyndarray作为类成员变量

2024-10-03 23:18:13 发布

您现在位置:Python中文网/ 问答频道 /正文

我期待着将Python对象传递给Boost Python类。这个对象有一个ndarray as属性,我想将这个ndarray作为私有成员变量存储在这个类中,以便以后使用。我找不到合适的方法来实现这一点,并且在将boost::python::numpy::ndarray变量声明为private时出现了编译器错误

这是我当前的代码:

#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>());
}

产生的错误消息是:

error: no matching function for call to ‘boost::python::numpy::ndarray::ndarray()’

这也是我的CMakeLists.txt,因此您可以重现此错误:

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

Tags: thenumpycmakemapobjectincludenprequired
2条回答

问题是FlatlandCBS的构造函数无效。 根据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.

您得到的错误-error: no matching function for call to ‘boost::python::numpy::ndarray::ndarray()’是编译器告诉您它试图使用默认的ndarray构造函数。这个类没有默认的构造函数,所以您需要在初始值设定项列表中指定一个不同的构造函数(就像您对m_railEnv所做的那样!)。这里最简单的解决方案是将map的初始化移到初始化器列表中,如下所示:

    FlatlandCBS(p::object railEnv) :
        m_railEnv(railEnv),
        map(
          p::extract<np::ndarray>(
            p::extract<p::object>(
              railEnv.attr("distance_map")
            ).attr("get")()
          )
        )
    { }

这不是最漂亮的代码,但它应该能工作

因此,在@unddoch的帮助下,终于有可能解决这个问题。事实证明,不可能在一行中使用两个extraxt函数,但不知何故,以下是可能的:

FlatlandCBS(p::object railEnv) :
   m_railEnv(railEnv),
   m_map(
     p::extract<np::ndarray>(
       railEnv
         .attr("distance_map")
       .attr("get")()
     )
   )

因此,如果要从python对象中提取多个值,只需在一行中执行尽可能多的.atrr()

相关问题 更多 >