如何使用Boost :: python包装派生模板类?

问题描述 投票:1回答:1

我有一个来自模板类的派生类:

template<typename X, typename Y>
class BaseFunction
{
    static void export_BaseFunction()
    {
        ?????
    };
};
class Function : public BaseFunction<pair<double, double>, double>
{
    Function() : BaseFunction<pair<double, double>, double>() {};
    static void export_Function()
    {
    BaseFunction::export_BaseFunction();
    boost::python::class_<Function, boost::python::bases<BaseFunction<pair<double, double>, double>>, boost::shared_ptr<Function>>("Function");

    }
};

所以Boost::Python要求我为BaseFunction创建一个类包装器,但我没有找到任何信息来编写模板类,只有模板函数。

我是否必须为每个基类定义一个类包装器?我是否要为模板类中使用的每种类型定义类包装器?

c++ templates boost-python
1个回答
2
投票

发生RuntimeError是因为没有满足class_Bases模板参数的要求:

bases<...>的特化,它指定了以前暴露的T的C ++基类

以前暴露的是explained

namespace python = boost::python;
python::class_<Base>("Base");
python::class_<Derived, python::bases<Base> >("Derived");

要解决RuntimeError,请:

  • 如果暴露的API不需要使用basesFunction执行向上转换或向下转换,则省略BaseFunction<...>信息。例如,如果没有任何暴露给Python的C ++函数的参数类型为BaseFunction<...>或者将Function对象作为BaseFunction<...>&返回,那么Boost.Python不需要知道类型关系。
  • 否则,需要公开基类,并且Function需要公开关系: namespace python = boost::python; typedef BaseFunction<pair<double, double>, double> function_base_type; python::class_<function_base_type>("Base"); python::class_<Function, python::bases<function_base_type> >("Function"); 注册BaseFunction的特定类型实例时,字符串标识符必须是唯一的。

下面是一个完整的例子,Function暴露BaseFunctionexport_BaseFunction()函数将检查它是否已经注册以防止有关重复转换的警告,并将使用C ++类型信息名称来消除BaseFunction的不同模板实例化之间的歧义。

#include <utility>  // std::pair
#include <typeinfo> // typeid
#include <boost/python.hpp>

template<typename X, typename Y>
class BaseFunction
{
public:
  static void export_BaseFunction()
  {
    // If type is already registered, then return early.
    namespace python = boost::python;
    bool is_registered = (0 != python::converter::registry::query(
      python::type_id<BaseFunction>())->to_python_target_type());
    if (is_registered) return;

    // Otherwise, register the type as an internal type.
    std::string type_name = std::string("_") + typeid(BaseFunction).name();
    python::class_<BaseFunction>(type_name.c_str(), python::no_init);
  };
};

class Function
  : public BaseFunction<std::pair<double, double>, double>
{
private:

  typedef BaseFunction<std::pair<double, double>, double> parent_type;

public:

  static void export_Function()
  {
    // Explicitly register parent.
    parent_type::export_BaseFunction();
    // Expose this type and its relationship with parent.
    boost::python::class_<Function, boost::python::bases<parent_type>,
        boost::shared_ptr<Function> >("Function");
  }
};

/// @brief Example function to demonstrate upcasting.
void spam(BaseFunction<std::pair<double, double>, double>&) {}

BOOST_PYTHON_MODULE(example)
{
  Function::export_Function();
  boost::python::def("spam", &spam);
}

互动用法:

>>> import example
>>> f = example.Function()
>>> f
<example.Function object at 0xb7ec5464>
>>> example.spam(f)
© www.soinside.com 2019 - 2024. All rights reserved.