Reputation: 412
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
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