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

Reply via email to