【问题标题】:Using Boost Python Numpy ndarray as a Class member variable使用 Boost Python Numpy ndarray 作为类成员变量
【发布时间】:2021-08-05 07:47:46
【问题描述】:

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

这是我当前的代码:

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

【问题讨论】:

    标签: python c++ numpy boost boost-python


    【解决方案1】:

    问题是FlatlandCBS 的构造函数无效。 根据cppreference

    在构成构造函数的函数体的复合语句开始执行之前,所有直接基、虚拟基和非静态数据成员的初始化都已完成。成员初始化器列表是可以指定这些对象的非默认初始化的地方。

    你得到的错误 - 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")()
              )
            )
        { }
    

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

    【讨论】:

      【解决方案2】:

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

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

      因此,如果您想从 python 对象中提取多个值,只需连续执行尽可能多的.atrr()

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-05-06
        • 1970-01-01
        • 1970-01-01
        • 2012-09-27
        • 2012-05-25
        • 2017-02-17
        • 2017-03-21
        相关资源
        最近更新 更多