I'm currently trying to put part of a complex program into a dynamic library. This part consists of some classes that are also wrapped with boost python into a module to be embedded again. Here is a simplified version of the dll source.
Hello.cpp:
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/python.hpp>
#include <Foo.h>
using namespace boost::python;
typedef boost::shared_ptr<Hello> hello_ptr;
BOOST_PYTHON_MODULE(Hello)
{
class_<Hello, hello_ptr>("Hello")
.def("say_hello", &Hello::say_hello)
;
};
void Hello::say_hello(){
cout << "Hello World!" << endl;
}
void World::foo(){
Py_Initialize();
try {
PyRun_SimpleString(
"hello = None\n"
"\n"
"def setup(hello_from_cxx):\n"
" print 'setup called with', hello_from_cxx\n"
" global hello\n"
" hello = a_foo_from_cxx\n"
"\n"
"def run():\n"
" hello.say_hello()\n"
"\n"
"print 'main module loaded'\n"
);
//initialize eviroment
initHello();
hello_ptr hello = boost::make_shared<Hello>();
object main = object(handle<>(borrowed(
PyImport_AddModule("__main__")
)));
// pass the reference to hello into python:
object setup_func = main.attr("setup");
setup_func(hello);
// now run the python 'main' function
object run_func = main.attr("run");
run_func();
}
catch (error_already_set) {
PyErr_Print();
}
}
Hello.h
#ifndef HELLO_H_INCLUDED
#define HELLO_H_INCLUDED
#include <iostream>
#include <boost/python.hpp>
using namespace std;
class Hello{
public:
void say_hello();
};
class World{
public:
void foo();
};
#endif // HELLO_H_INCLUDED
In the main function of the application I then create a instance of the class that embeds python but it gives an undefined reference to World::foo() even though the function is defined in the dynamic library libFoo.dll which is also linked against by the main application.
main.cpp:
#include <iostream>
#include <Hello.h>
using namespace std;
int main(){
cout << "Test" << endl;
World world;
world.foo();
}
Console:
undefined reference to `World::foo()'
I'm using Code::Blocks with MinGW.
This problem has kept me awake some days now and I can't seem to find a way to solve it. Hope you can help me.
Thanks in advance.
UPDATE:
I now tried to slove this task using the normal Python C API. There the step of defining the Python_Module (BOOST_PYTHON_MODULE()) to which this error is definitely connected, is done by defining a function like:
PyMODINIT_FUNC initHello(void){
...
}
Now writing infront of this
#define PyMODINIT_FUNC void
solves the error. Does anyone now how the boost.python library defines the BOOST_PYTHON_MODULE function? Maybe there is this kind of solution as well? I couldn't find any PyMODINIT_FUNC stuff in the source files.
Found the solution myself.
It's like I had already guessed. What is needed is to define BOOST_PYTHON_MODULE_INIT(name) like this.
# define BOOST_PYTHON_MODULE_INIT(name) \
void BOOST_PP_CAT(init_module_,name)(); \
extern "C" __attribute__ ((__visibility__("default"))) _BOOST_PYTHON_MODULE_INIT(name)
Actually I found this in one of the header files with some #ifdef infront but it seems that they're not working correctly. At least not for me.