Pybind11 ModuleNotFoundError when trying to import modules across different files

25 views Asked by At

Disclaimer, I have just started using Pybind11 and do not have much experience with C++. I've had success in using Pybind until I've needed to add inheritance. I am able to successfully generate a shared object file (e.g. derived_class.so), but get an error when trying to include it in my python project:

ModuleNotFoundError: No module named 'base_class'

I was trying to follow along with the docs, specifically the portion that talks about partitioning modules across multiple files

Below I've included a stripped down version to orchestrate what I'm working with and attempting to accomplish.

C++ Classes

// base_class.h
class BaseClass {
    public:
        BaseClass(int id): id(int id) {}
        int get_id() { return id; }
    private:
        int id;
}
// derived_class.h
#include "common/base_class"

class DerivedClass: public BaseClass {
    public:
        DerivedClass(int id);
}
// derived_class.cpp
#include "derived_class.h"

DerivedClass::DerivedClass(int id): BaseClass(id) {}

C++ Bindings

// base_class_binding.cpp

#include "base_class.h"
#include <pybind11/pybind11.h>

namespace py = pybind11;

PYBIND11_MODULE(base_class, m) {
    py::class_<BaseClass>(m, "BaseClass")
        .def(py::init<int>());
}
// derived_class_binding.cpp

#include "common/base_class.h"
#include "derived_class.h"
#include <pybind11/pybind11.h>

namespace py = pybind11;

PYBIND11_MODULE(derived_class, m) {
    //attempt to import module as per docs
    py::module_::import("base_class");
    
    // use of imported module class as per docs
    py::class_<DerivedClass, BaseClass>(m, "DerivedClass")
        .def(py::init<int>());
}

Library Generation

g++ -std=c++20 -shared -fpic `python3.12 -m pybind11 --includes` derived_class.cpp derived_class_binding.cpp common/base_class_binding.cpp -o derived_class.so

Python usage

# test.py
from derived_class import DerivedClass # THIS GENERATES EXCEPTION

if __name__ == '__main__':
    derivedClass = DerivedClass(1)
    print(f'The ID is: {derivedClass.get_id()}')

I'm expecting my library to import, and then utilize the get_id() function of the base class. I've tried various combinations of:

  • The alternate approach to import a module (py::object).
  • Including the base_class_binding.cpp into derived_class_binding.cpp directly (as opposed to using the module import.
  • Defining a new py::class_<BaseClass> within derived_class_binding.cpp, which works, but defeats the purpose of having modules escapsulated per file. It also means I need to redeclare it for all of the other files that use it.
0

There are 0 answers