【问题标题】:How to expose a templated class as one class to python with boost::python如何使用 boost::python 将模板类作为一个类公开给 python
【发布时间】:2016-09-12 14:44:41
【问题描述】:

在许多关于 boost::python 的示例中,您会看到类似以下内容:

using namespace boost::python;
typedef class_<std::vector<float>> VectorFloat;

当然,如果您需要double 向量,您将有第二个类,称为DoubleVector 左右。 在我看来,这不是很“pythonic”。如果 C++ 中的一个(模板化)类实际上是 python 中的一个类,它接受像, ..., type='float', ... , 这样的参数,那会更直观(我认为)。这样,该类在 pydocs 中也只出现一次,并且只需要添加一次到 boost::python module

假设我们有一个用于 C++ 代码的简单模板类:

template <typename T>
MyClass
{
    T val;

public:
    MyClass(const T& tVal) : val(tVal) {}

    T    getVal()              { return val; }
    void setVal(const T& tVal) { val = tVal; }
};

现在我们要为 Python 编写一个接口。到目前为止我的想法:

使用 boost::variant

typedef boost::variant<MyClass<float>, MyClass<double>> VariantClass;    

class MyPythonClass
{
    VariantClass vClass;

public:
    MyPythonClass(
        const PyObject& tVal, 
        const boost::python::str& type)
    {
        using namespace boost::python;
        std::string type_string = extract<std::string>(type);

        if( type_string == "float" )
        {
            float f = extract<float>(tVal);
            vClass = MyClass(f);
        }
        else if( type_string == "double" )
        {
            double d = extract<double>(tVal);
            vClass = MyClass(d);
        }
    }

    boost::python::PyObject* getVal()
    {
        // What to put here?
    }

    void setVal(const boost::python::PyObject& tVal)
    {
        //What to put here?
    }
};

BOOST_PYTHON_MODULE(my_module)
{
    class_<MyPythonClass>("MyClass", init<boost::python::PyObject, int, boost::python::str>).def("getVal", &MyClass::getVal());
}

这个解决方案的一个明显缺点是我猜 boost::variant 可以使用完全不同的类型,而我的类几乎相同,除了它们存储的数据类型。所以可能比必要的更多信息被抽象出来。

所以我猜这个问题归结为示例中的两个空函数。但是,当然也可以接受更简洁、更短或更少“if”链的答案。正如标题所说,它是关于模板类和 boost::python 而不一定是关于 boost::variant。

【问题讨论】:

  • 要将 boost::variant 转换为 python 对象,请使用 static_visitor。要以另一种方式转换,您需要在运行时询问 python 对象的类型。

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


【解决方案1】:

这里有几个混淆来源。首先,在 Python 中,object 基本上已经是一个变体——一切都是object。在 C++ 中,类模板不是类型——它是创建类型的秘诀。因此,如果您想将 MyClass&lt;T&gt; 从 C++ 公开到 Python,您应该只公开所有 MyClass&lt;T&gt;s

我会编写一个执行绑定的函数模板:

template <class T>
void bind_MyClass(const char* name) {
    class_<MyClass<T>>(name, init<T const&>())
        .add_property("val", &MyClass<T>::getVal, &MyClass<T>::setVal);
        ;
}

然后直接调用它:

bind_MyClass<float>("MyClassFloat");
bind_MyClass<double>("MyClassDouble");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-16
    • 1970-01-01
    • 2011-06-30
    • 2011-06-18
    • 2012-04-23
    • 1970-01-01
    • 2013-12-04
    • 2011-03-21
    相关资源
    最近更新 更多