I've attached a patch that implements what I think is a reasonable fix for the problem I found. Essentially, it implements BOOST_PYTHON_MODULE under python3 such that each invocation of the macro creates a new static PyModuleDef. I also reimplemented bp::detail::init_module for the python3 case to take a PyModuleDef parameter rather than a name.
As far as I can tell, these changes work well. I ran bjam in "libs/python/test" and didn't see any failures...I saw a lot of lines saying "**passed**", but none saying "**failed**", so I assume things are ok. If there are more tests that need to be run, please let me know, and tell me how to run them. I also tested the changes against a project which was manifesting the original problem I described, and the problems went away. That is, with the changes in this patch, my extension modules all have the correct "__name__" now. Austin On Mon, Dec 20, 2010 at 4:04 PM, Austin Bingham <austin.bing...@gmail.com> wrote: > I'm in the process of upgrading my project to boost-1.45.0 and > python3, and I started seeing strange problems with some of my > boost.python-based extension modules. Essentially, some of my modules > are reporting the wrong module name, i.e. if I > "print(module_object.__name__)", I get the wrong value. I threw this > into gdb, and it looks like the problem might have to do with the > implementation of bp::detail::init_module(). > > I ran python under gdb, but a breakpoint on init_module(), and > imported the modules with which I'm seeing problems. The first call to > init_module() initializes the static PyModuleDef struct "moduledef" > properly. However, the second call shows that the "m_name" field it > left as-is from the first call (since the object is static); I would > have expected that it needs to be updated with the new module name. > This stale (I think) module def is then used for the rest of the > initialization, and I'm guessing that this is the cause of the > problems I'm seeing. Certainly, it seems that the name of the first > module imported seems to be getting used as the name of the second > module. > > I only noticed this problem when I tried to pickle some of the types > exposed by my module. The pickle module in python3 complained that it > didn't know anything about the broken modules I was getting. > > Is this a bug in boost.python? I plan to write a small patch tomorrow > to set the m_name field in init_module(), so maybe this will fix the > problem. > > If this isn't a boost.python bug, does anyone have any idea what might > be going wrong? And how is it correct that the static moduledef is > reused without updating its name? > > Thanks, > Austin >
Index: boost/python/module_init.hpp =================================================================== --- boost/python/module_init.hpp (revision 67446) +++ boost/python/module_init.hpp (working copy) @@ -13,19 +13,43 @@ namespace boost { namespace python { namespace detail { +# if PY_VERSION_HEX >= 0x03000000 + +BOOST_PYTHON_DECL PyObject* init_module(PyModuleDef&, void(*)()); + +#else + BOOST_PYTHON_DECL PyObject* init_module(char const* name, void(*)()); +#endif + }}} # if PY_VERSION_HEX >= 0x03000000 -# define _BOOST_PYTHON_MODULE_INIT(name) \ - PyObject* BOOST_PP_CAT (PyInit_,name)() \ -{ \ - return boost::python::detail::init_module( \ - BOOST_PP_STRINGIZE(name),&BOOST_PP_CAT(init_module_,name)); \ -} \ - void BOOST_PP_CAT(init_module_,name)() +# define _BOOST_PYTHON_MODULE_INIT(name) \ + PyObject* BOOST_PP_CAT(PyInit_, name)() \ + { \ + using namespace boost::python; \ + \ + static PyMethodDef initial_methods[] = { { 0, 0, 0, 0 } }; \ + \ + static struct PyModuleDef moduledef = { \ + PyModuleDef_HEAD_INIT, \ + BOOST_PP_STRINGIZE(name), \ + 0, /* m_doc */ \ + -1, /* m_size */ \ + initial_methods, \ + 0, /* m_reload */ \ + 0, /* m_traverse */ \ + 0, /* m_clear */ \ + 0, /* m_free */ \ + }; \ + \ + return boost::python::detail::init_module( \ + moduledef, BOOST_PP_CAT(init_module_, name) ); \ + } \ + void BOOST_PP_CAT(init_module_, name)() # else Index: libs/python/src/module.cpp =================================================================== --- libs/python/src/module.cpp (revision 67446) +++ libs/python/src/module.cpp (working copy) @@ -9,6 +9,28 @@ #include <boost/python/scope.hpp> #include <boost/python/object/add_to_namespace.hpp> +namespace +{ + +PyObject* init_module_in_scope(PyObject* m, void(*init_function)()) +{ + using namespace boost::python; + + if (m != 0) + { + // Create the current module scope + object m_obj( + ((boost::python::detail::borrowed_reference_t*)m)); + scope current_module(m_obj); + + handle_exception(init_function); + } + + return m; +} + +} + namespace boost { namespace python { namespace detail { BOOST_PYTHON_DECL void scope_setattr_doc(char const* name, object const& x, char const* doc) @@ -19,6 +41,17 @@ objects::add_to_namespace(current, name, x, doc); } +#if PY_VERSION_HEX >= 0x03000000 + +PyObject* init_module(PyModuleDef& moduledef, void(*init_function)()) +{ + return ::init_module_in_scope( + PyModule_Create(&moduledef), + init_function); +} + +#else + namespace { PyMethodDef initial_methods[] = { { 0, 0, 0, 0 } }; @@ -26,35 +59,13 @@ BOOST_PYTHON_DECL PyObject* init_module(char const* name, void(*init_function)()) { -#if PY_VERSION_HEX >= 0x03000000 - static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - name, - 0, /* m_doc */ - -1, /* m_size */ - initial_methods, - 0, /* m_reload */ - 0, /* m_traverse */ - 0, /* m_clear */ - 0, /* m_free */ - }; - PyObject* m = PyModule_Create(&moduledef); -#else - PyObject* m - = Py_InitModule(const_cast<char*>(name), initial_methods); + return init_module_in_scope( + Py_InitModule(const_cast<char*>(name), initial_methods), + init_function); +} + #endif - if (m != 0) - { - // Create the current module scope - object m_obj(((borrowed_reference_t*)m)); - scope current_module(m_obj); - - handle_exception(init_function); - } - return m; -} - }}} // namespace boost::python::detail namespace boost { namespace python { Index: tools/build/v2/user-config.jam =================================================================== --- tools/build/v2/user-config.jam (revision 67446) +++ tools/build/v2/user-config.jam (working copy) @@ -34,6 +34,13 @@ # http://boost.org/boost-build2/doc/html/bbv2/advanced.html#bbv2.advanced.jam_language # +using python + : 3.1 + : /usr/bin/python3 + : /usr/include/python3.1 + : /usr/lib + : + ; # ------------------ # GCC configuration.
_______________________________________________ Cplusplus-sig mailing list Cplusplus-sig@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig