Simerax
Simerax

Reputation: 412

Pybind11 - Where to put PYBIND11_MODULE

Im currently playing around with pybind11 a bit. Im trying to create a C++ class which then gets passed to a python interpreter embedded in my C++ source.

I created some dummy class just to test the basic functionality I kept everything in a single source file. This approach compiled and ran without any problems.

Now I separated my dummy Class Test into a Test.h and Test.cpp

Test.h

#pragma once
#include<iostream>
#include"pybind11\pybind11.h"

namespace py = pybind11;

class Test
{
public:
    Test(const std::string &s);
    ~Test();

    void printStr();

private:
    std::string _s;
};

Test.cpp

#include "Test.h"

PYBIND11_MODULE(TestModule, m)
{
    py::class_<Test>(m, "Test") 
        .def(py::init<const std::string &>())
        .def("printStr", &Test::printStr); 
}


Test::Test(const std::string &s) : _s(s)
{

}
Test::~Test()
{

}

void Test::printStr()
{
    std::cout << "---> " << _s << std::endl;
}

main.cpp

#include"Test.h"

int main(int argc, char **argv)
{

    PyImport_AppendInittab("TestModule", PyInit_TestModule);
    Py_Initialize(); 

    PyRun_SimpleString("import TestModule");
    PyRun_SimpleString("t = TestModule.Test(\"str\")"); 
    PyRun_SimpleString("t.printStr()"); 
    Py_Finalize();

    getchar();

    return 1;
}

After putting the Class Test into a new file the Compiler cannot find the PyInit_TestModule (main.cpp line: 6) anymore since this is generated by the PYBIND11_MODULE Macro which lives in the Test.cpp file(MSVS2017 Error: C2065).

I tried putting the PYBIND11_MODULE Macro into the Test.h. This however resulted in a linker error which said that "_PyInit_TestModule" is already defined in main.obj (MSVS2017 Error: LNK2005)

Putting the PYBIND11_MODULE Macro in the main.cpp file works. However I feel like this will become quite unreadable as soon as you put a lot of custom Module definitions into main.cpp or even worse you have multiple Python-Interpreter being started from different source files where you then need to put the same definition in all those files which will be a mess and most likely turn into a linker error.

Has one of you faced the same Problem and how did you solve it?

Upvotes: 3

Views: 4627

Answers (1)

angelo.mastro
angelo.mastro

Reputation: 1784

I created a file of his own for the bindings, and compiled/linked it together with the original c++ file. This way:

1) Test.h + Test.cpp contain only c++ code of your class

2) Test-bindings.cpp contains the PYBIND11_MODULE and #include <Test.h>

3) Building (with cmake). You will get a PyTest.so file out of it, that you can load in python.

# c++ libray
add_library(TestLib SHARED /path/to/Test.h /path/to/Test.cpp)

# bindings
add_subdirectory(pybind11) # you must have downloaded this repo
include_directories(/path-only/to/Test.h)
pybind11_add_module(PyTest SHARED /path/to/Test-bindings.cpp /path/to/Test.cpp)

4) (I suggest you to) write the main in python, using the python-binding you just created

5) In your main.py

 import PyTest
 # do something

Upvotes: 4

Related Questions