我有一个暴露了两个C ++类的模块,它们都有方法foo()
:
struct MyClassA{
void foo() { std::cout << "MyClassA::foo()" << std::endl; }
};
struct MyClassB{
void foo() { std::cout << "MyClassB::foo()" << std::endl; }
};
BOOST_PYTHON_MODULE(my_module){
class_<MyClassA>("MyClassA", init<>()).def("foo", &MyClassA::foo);
class_<MyClassB>("MyClassB", init<>()).def("foo", &MyClassB::foo);
}
在Python中,我创建了一个派生自两个类的类:
from my_module import MyClassA, MyClassB
class Derived(MyClassA, MyClassB):
def foo(self):
super().foo() # should be unnessessary - doesn't work anyway
a = MyClassA()
a.foo() # works
b = MyClassB()
b.foo() # works
d = Derived()
d.foo() # only prints 'MyClassA::foo()'
现在,我希望d.foo()
致电MyClassA.foo()
以及MyClassB.foo()
。但是虽然Derived.mro()
看起来很好:
[<class '__main__.Derived'>, <class 'my_module.MyClassA'>, <class 'my_module.MyClassB'>, <class 'Boost.Python.instance'>, <class 'object'>]
..仅调用MyClassA.foo()
。
如何让C ++方法调用super()
方法?这对__init__()
也适用吗?
答案 0 :(得分:2)
C ++层无法直接访问Python用于通过private static String[] args;
private static ConfigurableApplicationContext context;
public static void main(String[] args) {
Main.args = args;
Main.context = SpringApplication.run(Main.class, args);
}
public static void restart() {
// close previous context
context.close();
// and build new one
Main.context = SpringApplication.run(Main.class, args);
}
自动执行超类调用的MRO信息。如果您使用Python的明确知识污染了C ++代码,则可以直接创建super
的对象(必须使用两个参数调用;启用no-arg PySuper_Type
的魔法将不可用)和使用它,但将Python代码与C ++代码混合起来会非常难看。
在实践中,使用Boost.Python的最佳建议可能是the same as for pybind11
(一种C ++ 11特定的仅限头的工具,其服务于类似的目的而不依赖于整个Boost生态系统),以及那里推荐的方法是显式调用C ++级父类方法,而不是通过super
隐式调用。没有合理的方法将C ++和Python方法合并到多重继承中,这种方法不会导致使用Python特定代码无可靠地污染非Python代码。 super
的方法是:
pybind11
答案 1 :(得分:0)
我当前的方法(改编自this回答)需要某种处理super()
- 手动调用的包装器。结果类不再需要任何特殊处理:
C ++代码:
struct MyClassA{
void foo() { std::cout << "MyClassA::foo()" << std::endl; }
};
struct MyClassB{
void foo() { std::cout << "MyClassB::foo()" << std::endl; }
};
BOOST_PYTHON_MODULE(my_module){
class_<MyClassA>("MyClassACpp", init<>()).def("foo", &MyClassA::foo);
class_<MyClassB>("MyClassBCpp", init<>()).def("foo", &MyClassB::foo);
}
<强>包装强>
from my_module import MyClassACpp, MyClassBCpp
def call_super(cls, instance, method, *args):
mro = instance.__class__.mro()
for next_class in mro[mro.index(cls) + 1:]:
if not hasattr(next_class, method):
continue
if next_class.__module__ in {'Boost.Python', 'builtins'}:
continue
getattr(next_class, method)(instance, *args)
if next_class.__module__ != 'my_module':
break
class MyClassA(MyClassACpp):
def __init__(self):
call_super(MyClassA, self, '__init__')
print('MyClassA.__init__()')
def foo(self):
call_super(MyClassA, self, 'foo')
class MyClassB(MyClassBCpp):
def __init__(self):
call_super(MyClassB, self, '__init__')
print('MyClassB.__init__()')
def foo(self):
call_super(MyClassB, self, 'foo')
<强>用法:强>
class Derived(MyClassA, MyClassB):
def foo(self):
super().foo()
d = Derived()
d.foo()
<强>输出:强>
MyClassA.__init__()
MyClassB.__init__()
MyClassA::foo()
MyClassB::foo()