【问题标题】:Boost python typedef提升python typedef
【发布时间】:2018-12-05 16:58:28
【问题描述】:

我正在尝试使用 boost python 将具有名称别名的 C++ 类公开给 python。

struct Foo
{
  void hi() const { std::cout << "hi" << std::endl; }
};

BOOST_PYTHON_MODULE(Example)
{
  typedef Foo Bar;

  class_<Foo>("Foo")
    .def("hi", &Foo::hi)
  ;

  class_<Bar>("Bar")
    .def("hi", &Bar::hi)
  ;
}

除了烦人的 RuntimeWarning 之外,代码按预期工作。

RuntimeWarning: to-Python converter for Foo already registered; second conversion method ignore

在 python 中添加Bar = Foo 也可以。但我需要将定义保留在同一个模块中。有没有更好的方法来实现这一点?

【问题讨论】:

    标签: python c++ boost-python


    【解决方案1】:

    我会采用 Ulrich 提到的“与 Python Bar = Foo 等效的 C++”方法。

    您可以使用boost::python::scope 来访问当前模块及其属性。

    #include <boost/python.hpp>
    #include <iostream>
    
    namespace bp = boost::python;
    
    struct Foo
    {
        void hi() const { std::cout << "hi" << std::endl; }
    };
    
    BOOST_PYTHON_MODULE(Example)
    {
        bp::class_<Foo>("Foo")
            .def("hi", &Foo::hi)
            ;
    
        bp::scope().attr("Bar") = bp::scope().attr("Foo");
    }
    

    【讨论】:

    • 哇。这正是我正在寻找的。谢谢。
    【解决方案2】:

    由于typedef 只引入了一个别名,您的代码只是以不同的名称注册了同一个类。

    建议:

    • 你为什么想要那个?只需以真实姓名注册一次。正如您所提到的,在 Python 中创建别名(同样,为什么?)很容易。
    • 如果您刚刚声明了一个基类并从中派生了FooBar,那么您将拥有不同的类型,并且警告也会消失。
    • 您可能还可以编写与 Python Bar = Foo 等效的 C++,即将对象简单地分配给模块命名空间中的名称。

    鉴于以下反馈需要支持遗留代码,我会这样做:

    // same as above
    struct Foo { ... };
    
    // For legacy reasons, it is mandatory that Foo is exported
    // under two names. In order to introduce new C++ types, we
    // just derive from the original Foo. The approach using a
    // typedef doesn't work because it only creates an alias but
    // not an existing type.
    struct FooType: Foo {};
    struct BarType: Foo {};
    
    BOOST_PYTHON_MODULE(Example)
    {
      class_<FooType>("Foo")
        .def("hi", &FooType::hi)
      ;
      class_<BarType>("Bar")
        .def("hi", &BarType::hi)
      ;
    }
    

    【讨论】:

    • 感谢您的建议。困境来自这样一个事实,即我无法对遗留的 C++ 类定义进行太多更改。另外,我正在为希望一切都在一个模块加载的用户创建一个 python 模块。但是,我无法理解您的最后一点。与 Python 中的别名等效的 C++ 应该是 typedefusing。它们在纯 C++ 中运行良好。但我仍然需要在示例模块中定义Bar
    • 是和不是。使用typedefusing,您可以创建一个别名。但是,原始名称和别名都指的是同一类型。您想要的是不同的类型,即使它的行为应该相似。换句话说,你想要平等而不是身份。我将尝试用示例代码来说明这部分。
    • 我需要的实际上是别名,即引用相同的类型。您的技术也有效,但我仍然期待其他一些技巧可以通过提升以最小的编码复杂性来实现它。
    猜你喜欢
    • 2011-07-11
    • 2013-02-20
    • 1970-01-01
    • 1970-01-01
    • 2011-06-08
    • 2011-03-28
    • 1970-01-01
    • 2012-03-07
    • 1970-01-01
    相关资源
    最近更新 更多