将 `__str__` 方法添加到 Boost Python C++ 类时的构建问题

Posted

技术标签:

【中文标题】将 `__str__` 方法添加到 Boost Python C++ 类时的构建问题【英文标题】:Build problems when adding `__str__` method to Boost Python C++ class 【发布时间】:2010-05-13 17:31:01 【问题描述】:

我已经开始尝试使用 boost python 并遇到了一个问题。我试图将一个 C++ 类暴露给没有问题的 python。但我似乎无法为该类实现__str__ 功能而不会出现我不理解的构建错误。

我正在使用 boostpro 的 boost 1_42 prebuild。我使用 cmake 和 vs2010 编译器构建库。

我有一个非常简单的设置。头文件 (tutorial.h) 如下所示:

#include <iostream>
namespace TestBoostPython
    class TestClass 
        private:
            double m_x;
        public:
            TestClass(double x);
            double Get_x() const;
            void Set_x(double x);
    ;
    std::ostream &operator<<(std::ostream &ostr, const TestClass &ts);
;

相应的 cpp 文件如下所示:

#include <boost/python.hpp>
#include "tutorial.h"

using namespace TestBoostPython;

TestClass::TestClass(double x)

    m_x = x;


double TestClass::Get_x() const

    return m_x;

void TestClass::Set_x(double x)

    m_x = x;


std::ostream &operator<<(std::ostream &ostr, const TestClass &ts)

    ostr << ts.Get_x() << "\n";
    return ostr;


BOOST_PYTHON_MODULE(testme)

using namespace boost::python;
class_<TestClass>("TestClass", init<double>())
    .add_property("x", &TestClass::Get_x, &TestClass::Set_x)
    .def(str(self))
    ;

CMakeLists.txt 如下所示:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)

project (testme)

FIND_PACKAGE( Boost REQUIRED )
FIND_PACKAGE( Boost COMPONENTS python REQUIRED )
FIND_PACKAGE( PythonLibs REQUIRED )

set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREAD ON)

INCLUDE_DIRECTORIES($Boost_INCLUDE_DIRS)
INCLUDE_DIRECTORIES ( $PYTHON_INCLUDE_PATH )

add_library(testme SHARED tutorial.cpp)
target_link_libraries(testme $Boost_PYTHON_LIBRARY)
target_link_libraries(testme $PYTHON_LIBRARY

我得到的构建错误如下:

Compiling...
tutorial.cpp
    C:\Program Files (x86)\boost\boost_1_42\boost/python/def_visitor.hpp(31) : error C2780: 'void boost::python::api::object_operators::visit(ClassT &,const char *,const boost::python::detail::def_helper &) const' : expects 3 arguments - 1 provided
    with
    [
        U=boost::python::api::object
    ]
    C:\Program Files (x86)\boost\boost_1_42\boost/python/object_core.hpp(203) : see declaration of 'boost::python::api::object_operators::visit'
    with
    [
        U=boost::python::api::object
    ]
    C:\Program Files (x86)\boost\boost_1_42\boost/python/def_visitor.hpp(67) : see reference to function template instantiation 'void boost::python::def_visitor_access::visit,classT>(const V &,classT &)' being compiled
    with
    [
        DerivedVisitor=boost::python::api::object,
        classT=boost::python::class_,
        V=boost::python::def_visitor
    ]
    C:\Program Files (x86)\boost\boost_1_42\boost/python/class.hpp(225) : see reference to function template instantiation 'void boost::python::def_visitor::visit>(classT &) const' being compiled
    with
    [
        DerivedVisitor=boost::python::api::object,
        W=TestBoostPython::TestClass,
        classT=boost::python::class_
    ]
    .\tutorial.cpp(29) : see reference to function template instantiation 'boost::python::class_ &boost::python::class_::def(const boost::python::def_visitor &)' being compiled
    with
    [
        W=TestBoostPython::TestClass,
        U=boost::python::api::object,
        DerivedVisitor=boost::python::api::object
    ]

有人知道出了什么问题吗?如果我从包装器代码中删除 .def(str(self)) 部分,一切都可以正常编译,并且该类可以从 python 中使用。非常感谢您的帮助。

谢谢你, 里卡德

编辑:忘记了一个常量

【问题讨论】:

不错!我最初并没有仔细看,而是在类本身中定义了 operator 【参考方案1】:

我最近遇到了这个问题; 有效的解决方案是明确解决这一行的strself

.def(str(self))

这样就变成了:

.def(self_ns::str(self_ns::self))

我不知道为什么这是必要的,(知道一些在 boost python 中发生的重载解决复杂性,它可能在那里......)但它对我有用:)

【讨论】:

太棒了!非常感谢。我喜欢 boost::python,但是当事情像这样变得混乱时,我认为在 Python C-API 中手动包装对象可能会更容易。我永远不会自己找到这个解决方案。再次感谢。 今天这仍然对我有用。我想知道这不是很久以前就应该修复的吗...? 有一个 boost::python::str 和一个 boost::python::self_ns::str,它们是非常不同的东西。这是必要的,因为如果你的代码有using boost::python(可能很多),编译器会找到前者,这会很混乱。 库将 self_t 隔离在其自己的命名空间 self_ns 中,以防止在其他上下文中通过参数相关查找找到对其进行操作的通用运算符模板。这应该被视为一个实现细节,因为用户永远不必直接提及 self_t。 boost.org/doc/libs/1_72_0/libs/python/doc/html/reference/… boost::python::str 是一个字符串对象,而 self_ns::str 是一个函数定义。此外,他们打算将其作为上述实现细节。【参考方案2】:

我遇到了同样的事情。添加这一行(而不是限定 str 和 self)也可以:

using self_ns::str;

【讨论】:

以上是关于将 `__str__` 方法添加到 Boost Python C++ 类时的构建问题的主要内容,如果未能解决你的问题,请参考以下文章

管理员错误:__str__ 返回非字符串(NoneType 类型)

Apollo boost - 查询中的 __typename 防止新的突变

linux添加boost路径

boost_1_63_0在Win10上VS2015编译

一种将 boost::posix_time::ptime 转换为 __int64 的方法

VS2010下编译配置Boost_1.53