'How to hold a Python object in C++ with PyBind11?

I'm using pybind11 to implement co-operation between Python and C++.

My target is that the main process is implemented with C++, and a Python interpreter is integrated into the c++ executable. Most housekeeping logic is coded with C++, little high-level core logic will be coded with Python so as to rapidly change the algorithm. I defined a virtual class named BaseClass in C++, and derive it in Python with a name DerivedClass, and then want to manage the life cycle of the objects in C++.

My question is How to dynamically create a Python object in C++, and hold it, and release it in C++? So far I can only get a BaseClass obj if I create a DerivedClass obj and assign it to a C++ variable.

The C++ codes:

#include <pybind11/embed.h>
#include <pybind11/pybind11.h>
#include <iomanip>
#include <iostream>
namespace py = pybind11;
using namespace py::literals;

class BaseClass {
public:
    virtual ~BaseClass() { std::cout << "Destroy():" << std::hex << ",this:" << this << std::endl; };
    BaseClass() { std::cout << "BaseClass():" << std::hex << ",this:" << this << std::endl; };
    BaseClass( const BaseClass& o_ ) {
        std::cout << "BaseClass() copying" << std::hex << ",this:" << this << ",from:" << &o_ << std::endl; };
    BaseClass( BaseClass&& o_ ) {
        std::cout << "BaseClass() moving" << std::hex << ",this:" << this << ",from:" << & o_ << std::endl; };
    BaseClass& operator=( BaseClass&& o_ ) {
        std::cout << "MovingAssignment" << std::hex << ",this:" << this << ",from:" << & o_ << std::endl;
        return *this;
    };
    BaseClass& operator=( const BaseClass& o_ ) {
        std::cout << "CopyingAssignment" << std::hex << ",this:" << this << ",from:" << & o_ << std::endl;
        return *this;
    };

    virtual void showMe() {
        std::cout << "show BaseClass" << std::hex << ",this:" << this << std::endl;
    };
};

class BaseClassPy : public BaseClass {
    using BaseClass::BaseClass;

    void showMe() override {
        PYBIND11_OVERRIDE(
            void,
            BaseClass,
            showMe
        );
    };
};

PYBIND11_EMBEDDED_MODULE( ModuleEmbed, m ) {
    py::class_<BaseClass, BaseClassPy>( m, "BaseClass" )
    .def( py::init<>() )
    .def( "showMe", &BaseClass::showMe );
};

int main() {
    py::scoped_interpreter guard {};

    auto mod_py = py::module_::import( "ModulePy" );
    auto py_obj = mod_py.attr( "DerivedClass" )().cast<BaseClass>();
    py_obj.showMe();
};

The Python code(file: ModulePy.py):

import ModuleEmbed
class DerivedClass( ModuleEmbed.BaseClass ):
    def __init__( self ):
        print( "DerivedClass() in Python" )
        super().__init__()

    def showMe( self ):
        print( "show DerivedClass" )

The result output:

DerivedClass() in Python

BaseClass():,this:0x5631d27abc50

BaseClass() moving,this:0x7ffe43976010,from:0x5631d27abc50

Destroy():,this:0x5631d27abc50

show BaseClass,this:0x7ffe43976010

Destroy():,this:0x7ffe43976010



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source