I created a program that exposes class with virtual function to python using boost::python. Also I configured everything so that I could load python module that was created by boost::python and retrieve an instance of that object and it's child in python module. But I couldn't extract the python object with type Base or Alpha to Base * pointer.
I have the same error as here
Source code for main:
Py_Initialize();
try {
auto sys_module {bp::import("sys")};
auto sys_path {sys_module.attr("path")};
sys_path.attr("append")("bin");
bp::import("py_lib");
auto module_test {bp::import("module_test").attr("__dict__")};
const char* ident = bp::extract< const char* >( module_test["Ident"]() );
const char* newgameplay = bp::extract< const char* >( module_test["NewGamePlay"]() );
printf("Loading Script: %s\n", ident);
auto py_interface_inst {module_test[newgameplay]()};
const auto is_subclass {bp::is_subclass
bp::extract<Base *> extractor {py_interface_inst};
if (extractor.check()) {
auto cpp = extractor();
cpp->FunctionCall();
}
} catch (const boost::python::error_already_set&) {
PyErr_Print();
}
return 0;
Module defenition code:
class Base
{
public:
Base() {};
virtual void FunctionCall() {std::cout << "Base";}
virtual ~Base() {};
};
class BaseWrap : public Base, public bp::wrapper<Base>
{
public:
void FunctionCall() override
{
if (bp::override f = this->get_override("FunctionCall"))
f();
else Base::FunctionCall();
}
};
BOOST_PYTHON_MODULE(PY_MODULE_NAME)
{
class_<BaseWrap, boost::noncopyable>("Base")
.def("FunctionCall", &Base::FunctionCall, &BaseWrap::FunctionCall)
;
class_<Hello>("Hello")
;
class_<HelloDerived, bases<Base>>("HelloDerived")
;
}
and python code file
import sys
import py_lib
def Ident():
return "Alpha"
def NewGamePlay():
return "NewAlpha"
def NewAlpha():
import py_lib
class Alpha(py_lib.Base):
def __init__(self):
super().__init__()
print("Made new Alpha!")
def FunctionCall(self):
print("This is function test Alpha!")
base : py_lib.Base = py_lib.Base()
derived : py_lib.Base = Alpha()
for el in [base, derived]:
el.FunctionCall()
return Alpha()
While debugging it seems that the extractor fails on python function
PyAPI_FUNC(int) PyType_IsSubtype(PyTypeObject *, PyTypeObject *);
This is in the function
// ..\boost_1.84.0\libs\python\src\object\class.cpp
BOOST_PYTHON_DECL void*
find_instance_impl(PyObject* inst, type_info type, bool null_shared_ptr_only)
{
if (!Py_TYPE(Py_TYPE(inst)) ||
!PyType_IsSubtype(Py_TYPE(Py_TYPE(inst)), &class_metatype_object))
return 0;
instance<>* self = reinterpret_cast<instance<>*>(inst);
...
If i skip this check and go straight to the reinterpret_cast then everything is great. I'm able to call methods of Base and overriden methods of Alpha.
I use msvc143 for compiling, CMake for building and boost 1.84 for boost::python.
While executing Bases' construtor is called, so the base object is created for sure.
Can you help me to undertand what could be the problem? Thanks