如何在Boost::Python中为C++类型添加自定义隐式转换?

2 投票
6 回答
2490 浏览
提问于 2025-04-15 13:29

在我的C++代码中,有一个叫做Foo的类,它里面有很多方法,这些方法需要一个Bar类型的变量作为参数:

class Foo {
public:
  void do_this(Bar b);
  void do_that(Bar b);
  /* ... */
};

Bar类有很多构造函数,可以用一些常见的类型来创建新的对象,比如int、std::string、float等等:

class Bar {
public:
  Bar(int i);
  Bar(float f);
  Bar(std::string s);
  /* ... */
};

我用Boost::Python把这个包裹起来,现在我可以直接用Python的字面量来调用我的Foo方法,因为这些字面量会自动转换成Bar对象。

f = Foo()
f.do_this(5)
f.do_that("hello")

现在,我还想使用其他的Python类型,比如元组,像这样:

f.do_that((1,2,3))

但是我不想修改原来的Bar定义,也不想让我的C++库里充满Boost::Python的东西。我想在我的绑定代码中写一个包装函数,但我就是搞不懂这是否可行,以及该怎么做。

换句话说:我能注册一个工厂函数,让它在Python中自动进行转换吗?

6 个回答

0

创建一个叫做 TupleCollector 的东西,并且重写它的“operator ,(int)”这个功能,这样你就可以写出一些特定的代码。

f.do_that((TuppleCollector(), 1, 2, 3))

最后,要实现 TupleCollector 和你想要的目标之间的转换。

1

在你的头文件里添加一个新的构造函数,写成 template <typename T> Bar(T)。然后实现这个构造函数,代码写成 template <> Bar::Bar(Tupple) {}

2

在包装代码附近创建一个名为Bar的子类,并给这个子类写一个构造函数,这个构造函数需要接收一个bp::object(或者更具体的Python类型)。

struct Bar_wrapper:Bar,bp::wrapper<Bar>
{
    Bar_wrapper(bp::object arg)
    {
        //code to build a Bar_wrapper Here
    }
}

然后把这个Bar_wrapper导出到Python中,而不是直接导出Bar,并且在Python中把它叫做Bar:

class<Bar_wrapper>("Bar")
    ...
    .def(init<bp::object>())
    ...

撰写回答