带函数模板的Python类:如何从外部添加实例? 总结 是否有一种方法(在C++中,而不是在Python中)为Boox::Python中的类添加额外的函数模板实例化(通过注入、重新打开定义、注册所需实例等)?< /P> 背景
给定一个包含函数模板成员的类(不是类模板),我想使用Boost::Python生成Python绑定 但是,在编写库时,我事先不知道将使用哪些模板参数调用成员函数。这意味着,我不能在Boost::Python类定义中列出它们 例子 假设我们有一个类带函数模板的Python类:如何从外部添加实例? 总结 是否有一种方法(在C++中,而不是在Python中)为Boox::Python中的类添加额外的函数模板实例化(通过注入、重新打开定义、注册所需实例等)?< /P> 背景,python,c++,templates,boost,export,Python,C++,Templates,Boost,Export,给定一个包含函数模板成员的类(不是类模板),我想使用Boost::Python生成Python绑定 但是,在编写库时,我事先不知道将使用哪些模板参数调用成员函数。这意味着,我不能在Boost::Python类定义中列出它们 例子 假设我们有一个类class,它有函数模板(带重载),还有两个测试类SomeClass和OtherClass,如下所示: class AnotherClass { public: std::string Name() { return &q
class
,它有函数模板(带重载),还有两个测试类SomeClass
和OtherClass
,如下所示:
class AnotherClass
{
public:
std::string Name()
{
return "AnotherClass";
}
};
add_to_the_class(AnotherClass);
// or
add_to_class_definition<AnotherClass>("TheClass");
// or whatever works...
类定义
由此得出:
Called Foo(SomeClass)
Called Foo(OtherClass)
Called Bar(SomeClass, 42)
Called Bar(OtherClass, 42)
Called Bar(SomeClass, Hello World)
Called Bar(OtherClass, Hello World)
问题:
在本例中,Foo()和Bar()函数模板的实例化是在Boost::Python类定义中创建的(请参见源代码中的注释)。这意味着,如果不修改这段代码,库的用户就不能添加新的实例化
因此,我所寻找的是一种方法
- 从Boost::Python类定义的外部“注入”这些实例化
- 以某种方式重新打开定义
- 在调用Boost::Python类定义之前,在某处注册所需的实例化
class AnotherClass
{
public:
std::string Name()
{
return "AnotherClass";
}
};
add_to_the_class(AnotherClass);
// or
add_to_class_definition<AnotherClass>("TheClass");
// or whatever works...
另一个类
{
公众:
std::string Name()
{
返回“另一个类”;
}
};
将_添加到_类(另一个类);
//或
将“类”添加到“类”定义(“类”);
//或者任何有用的东西。。。
这有可能吗?有没有其他方法可以达到类似的效果?过了一段时间,我找到了一个解决方案,并认为这对其他人来说可能也很有趣 解决方案 它实际上非常简单:
boost::python::class\uz
定义返回(当然)类型为boost::python::class\uz
的类实例。这可以存储,因此我们可以稍后向其中添加成员定义:
static auto the_class_ = boost::python::class_< TheClass > ( "TheClass" )
// add some .def(...) and so on here, if needed
;
template <class T>
void add_to_the_class()
{
the_class_
.def(
"Foo",
( void ( TheClass::* )( T& ))( &TheClass::Foo ),
( boost::python::arg("arg") )
)
.def(
"Bar",
( void ( TheClass::* )( T&, std::string ))( &TheClass::Bar ),
( boost::python::arg("arg"), boost::python::arg("param") )
)
.def(
"Bar",
( void ( TheClass::* )( T&, int ))( &TheClass::Bar ),
( boost::python::arg("arg"), boost::python::arg("param") )
)
;
}
static auto the\u class\uu=boost::python::class\uu(“TheClass”)
//如果需要,在这里添加一些.def(…)等等
;
模板
void将_添加到_类()
{
班_
def(
“福”,
(void(类::*)(T&)(类::Foo),
(boost::python::arg(“arg”))
)
def(
“酒吧”,
(void(类::*)(T&,std::string))(&TheClass::Bar),
(boost::python::arg(“arg”),boost::python::arg(“param”))
)
def(
“酒吧”,
(void(类::*)(T&,int))(&TheClass::Bar),
(boost::python::arg(“arg”),boost::python::arg(“param”))
)
;
}
现在,我们可以根据需要从外部向该定义添加任意多的额外重载:
add_to_the_class<AnotherClass>();
将_添加到_类();
这也消除了丑陋的宏
一些额外的见解
这一切都是有效的,因为到Python的实际绑定是在运行时创建的。在Posith::Python绑定代码中,实际上只定义了一些类和函数,这些函数和函数在主()之前调用,以启动C++代码和Python解释器之间的实际连接。
我认为,boost::python帮助中没有很好地记录这一点。我花了一段时间才弄明白。起初,我认为boost::python(通过一些模板魔术)会在编译时生成绑定。如果这是真的,上述解决方案将不起作用。事后看来,我现在完全明白了这一点
此外,这一见解(绑定是在运行时完成的,使用您提供的定义)还让我想到编写一个静态寄存器类,该类收集要导出到Python的类。这将进一步帮助我的库方法,因为我不必为每个新类扩展主BOOST\u PYTHON\u模块
定义,而只需将类注册到静态寄存器(可能再次使用一些宏…)。但这是未来的工作。。。现在问题解决了 对于您的附带问题,提供了一种非侵入式扩展类的通用方法,同时避免重复代码。
static auto the_class_ = boost::python::class_< TheClass > ( "TheClass" )
// add some .def(...) and so on here, if needed
;
template <class T>
void add_to_the_class()
{
the_class_
.def(
"Foo",
( void ( TheClass::* )( T& ))( &TheClass::Foo ),
( boost::python::arg("arg") )
)
.def(
"Bar",
( void ( TheClass::* )( T&, std::string ))( &TheClass::Bar ),
( boost::python::arg("arg"), boost::python::arg("param") )
)
.def(
"Bar",
( void ( TheClass::* )( T&, int ))( &TheClass::Bar ),
( boost::python::arg("arg"), boost::python::arg("param") )
)
;
}
add_to_the_class<AnotherClass>();