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
<[email protected]> 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
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig