[C++-sig] static/dynamic boost::python conflicts?

Koichi Tamura hohehohe2 at gmail.com
Mon Aug 4 09:18:45 CEST 2008


Hello,
I've experienced a trouble about boost.python linking (or Python itself) and
I've separated what is causing trouble from my source.
The condition is

- An application (m) loads two libraries dynamically.
- One of  them  (a)  creates a Python module, calls its init function, and
uses it internally. boost.python is statically linked with (a).
- The other (b) linkes boost.python dynamically
- The application (m) loads (b) first, then loads (a)

In this condition, (a)'s module is broken.

If anybody experienced it, or knows what's going on and how to make the
module working, please let me know.
Thanks in advance.

-Koichi


Here's the test code. (a) is a.cpp and (b) is b.cpp, (m) is main.cpp here.

$ cat a.cpp
#include <boost/python.hpp>

using namespace boost::python;

struct World
{
  std::string greet(){return "hello";}
};

BOOST_PYTHON_MODULE(hello)
{
  class_<World>("World")
    .def("greet", &World::greet);
}

extern "C"
{

void pycall()
{
	Py_Initialize();
	PyRun_SimpleString("print 'pycall'");
	inithello();
	object o_main(handle<>(borrowed(PyImport_AddModule("__main__"))));
	object o_hello(handle<>(PyImport_ImportModule("hello")));
	o_main.attr("hel") = o_hello;
	PyRun_SimpleString("print hel.World().greet()");
}

}
$ cat b.cpp
$ cat main.cpp
#include <dlfcn.h>

int main()
{
  void* handle0 = dlopen("b.bundle", RTLD_NOW);
  void* handle = dlopen("a.bundle", RTLD_NOW);

  typedef void (*func)();
  func myfunc;
  myfunc = (func)dlsym(handle, "pycall");
  myfunc();
  dlclose(handle);

  return 0;
}
$ gcc -o a.bundle -bundle
-I/System/Library/Frameworks/Python.framework/Versions/2.5/include/python2.5
-L/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/config
-lpython2.5 -lstdc++ a.cpp -lboost_python-mtstatic-1_35
$ gcc -o b.bundle -bundle
-I/System/Library/Frameworks/Python.framework/Versions/2.5/include/python2.5
-L/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/config
-lpython2.5 -lstdc++ b.cpp -lboost_python-mt-1_35
$ gcc main.cpp -lstdc++
$ ./a.out
pycall
Traceback (most recent call last):
  File "<string>", line 1, in <module>

AttributeError: 'module' object has no attribute 'World'


I've tested some more.

- It works if I comment out void* handle0 = dlopen("b.bundle", RTLD_NOW);
- It works if I call dlclose(handle0) just after void* handle0 =
dlopen("b.bundle", RTLD_NOW);
- except inithello(); it is working fine.
- It works if I separate the hello module, create hello.so, and import it
later.
- If I do one of the following things:
    1) dynamically link a.bundle and boost::python
    2) statically link b.bundle and boost::python
    3) dynamically link a.bundle and boost::python, and statically link
b.bundle and boost::python

I cannot use PyImport_AppendInittab() nor PyImport_ExtendInittab(), since
Python interpreter may be already running when
my code is first executed. I can separate my extension but I'd rather not.




2008/7/23 Koichi Tamura <hohehohe2 at gmail.com>

> Hello,
> I'm using boost::python and I've got a problem now.
>
>  I'm writing a shared library(bundle, I'm using MacOSX10.5, and it's a
> plug-in for some
> application) where I have a code like this.
>
>     //....on init....
>     if ( ! Py_IsInitialized())
>     {
>         int a = PyImport_AppendInittab("MyModule", &initMyModule);
>         Py_Initialize();
>         PyEval_InitThreads();
>         PyEval_ReleaseLock();
>     }
>
>     //....somewhere else...
>     PyGILState_STATE state = PyGILState_Ensure();
>     module = object(handle<>(PyModule_New(moduleName)));
>     myMod = object(handle<>(PyImport_ImportModule("MyModule")));
>     module.attr("mymod") = myMod;
>     PyGILState_Release(state);
>
> I statically linked boost::python, and it works fine. When imported,
> MyModule is
> filled with classes that boost::python has wrapped.
>
> But when I use another shared library(#) which dynamically links
> boost::python
> together with mine, PyImport_ImportModule("MyModule") returns a module
> which dict
> is empty but __doc__ and __name__.
>
> Instead of (#) I made a test shared library that does nothing but linking
> boost::python dynamically, and it still fails.
>
> Why does all statically linked boost::python and extension is affected by a
> dynamically
> linked boost::python? I'm really puzzled.
>
>
> I would really appreciate if anybody could help.
>
> -Koichi
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20080804/bcb51c0a/attachment.htm>


More information about the Cplusplus-sig mailing list