最小的例子;请注意,由于Base不是纯虚拟的事实而使情况变得复杂。我们去了:
baz.cpp:
#include
#include
using std::string;
namespace py=boost::python;
struct Base{
virtual string foo() const { return "Base.foo"; }
// fooBase is non-virtual, calling it from anywhere (c++ or python)
// will go through c++ dispatch
string fooBase() const { return foo(); }
};
struct BaseWrapper: Base, py::wrapper{
string foo() const{
// if Base were abstract (non-instantiable in python), then
// there would be only this->get_override("foo")() here
//
// if called on a class which overrides foo in python
if(this->get_override("foo")) return this->get_override("foo")();
// no override in python; happens if Base(Wrapper) is instantiated directly
else return Base::foo();
}
};
BOOST_PYTHON_MODULE(baz){
py::class_("Base")
.def("foo",&Base::foo)
.def("fooBase",&Base::fooBase)
;
}
bar.py
import sys
sys.path.append('.')
import baz
class PyDerived(baz.Base):
def foo(self): return 'PyDerived.foo'
base=baz.Base()
der=PyDerived()
print base.foo(), base.fooBase()
print der.foo(), der.fooBase()
生成文件
default:
g++ -shared -fPIC -o baz.so baz.cpp -lboost_python `pkg-config python --cflags`
结果是:
Base.foo Base.foo
PyDerived.foo PyDerived.foo
在这里您可以看到fooBase()(非虚拟c ++函数)如何调用virtual foo(),无论使用c ++还是python,它都会解析为重写。您可以从c ++中的Base派生一个类,它的工作原理相同。
编辑(提取c ++对象):
PyObject* obj; // given
py::object pyObj(obj); // wrap as boost::python object (cheap)
py::extract ex(pyObj);
if(ex.check()){ // types are compatible
Base& b=ex(); // get the wrapped object
// ...
} else {
// error
}
// shorter, thrwos when conversion not possible
Base &b=py::extract(py::object(obj))();
py::object从构造PyObject*并用于py::extract查询python对象是否与您要提取的内容匹配:PyObject* obj; py::extract extractor(py::object(obj)); if(!extractor.check()) /* error */; Base& b=extractor();