如何解决在 AMD64 Win Python35_d.lib 中缺少 PyModule_Create2?

How to work around missing PyModule_Create2 in AMD64 Win Python35_d.lib?

我正在尝试调试在 32 位 Python 2.7 中运行良好但在 64 位 Python 3.5 中运行不佳的扩展模块。

我使用了 Python.org 的 AMD64 Web 安装程序,但在 link 我得到了

__imp_PyModule_Create2 (referenced in libboost_python-vc120-mt-gd-1_57.lib(module.obj))

未解决。这是唯一未解析的符号。

这是故意的吗?我看到一份旧的错误报告,它似乎表明 Stable ABI 免于调试构建。 (这就是为什么我在 SO 上发帖而不是提交错误报告)

如果是故意的,我是不是应该先 link 然后再 python35_d.lib 然后 python35.lib,还是有其他方法可以解决这个问题?

我在这里发现了这个问题; AMD64 因素无关紧要。

关键是 Boost Python 库期望 link 反对 Python 的发布版本,即使它是 Boost Python 的调试版本。通过尝试 link 依赖于 Boost Python 的扩展模块,Boost 的

config/auto_link.hpp

将(默认情况下)创建一个 link 依赖项 -- 使用

#pragma comment(lib, string_of_library_name)

-- 在 python35.lib 上。如果您在扩展模块的 makefile 中指定了 python35_d.lib,并且期望您的 python 将被调用为 python35_d.exe.

,那么这是个坏消息

我通过 运行

找到了这个
dumpbin /EXPORTS python35.lib > python35_exp.txt
dumpbin /EXPORTS python35_d.lib > python35_d_exp.txt

并比较两者。主要区别在于发布版本导出符号 PyModule_Create2 和 PyModule_FromDefAndSpec2,而调试版本导出 PyModule_Create2TraceRefs 和 PyModule_FromDefAndSpec2TraceRefs。这显然是 Python 开发人员的故意选择,以确保调试扩展模块仅适用于调试 Python。在 Python 源代码中,include/object.h 中的第一行之一是

/* Py_DEBUG implies Py_TRACE_REFS. */
#if defined(Py_DEBUG) && !defined(Py_TRACE_REFS)
#define Py_TRACE_REFS
#endif

赠品在include/modsupport.h

#ifdef Py_TRACE_REFS
 /* When we are tracing reference counts, rename module creation functions so
    modules compiled with incompatible settings will generate a
    link-time error. */
 #define PyModule_Create2 PyModule_Create2TraceRefs
 #define PyModule_FromDefAndSpec2 PyModule_FromDefAndSpec2TraceRefs
#endif

解决方案是构建专门针对 python35_d.lib link 的特殊版本的 Boost 库。涉及几个步骤:

  • 运行 'bootstrap.bat --with-python="C:\Program Files\Python35"'
  • 在您的主目录中编辑用户-config.jam,使其看起来像(空格很重要)
    using python : 3.5 : C:\PROGRA~1\Python35 ;
    using python : 2.7 : C:\Python27 ;
    using python : 3.5 : C:\PROGRA~1\Python35\python_d
      : # includes
      : # libs
      : <python-debugging>on ;
  • 使用额外选项 "python-debugging=on" 调用 b2.exe,就像这样
.\b2.exe toolset=msvc-12.0 threading=multi variant=debug address-model=64 --with-python --debug-configuration python-debugging=on stage

请注意,要解决依赖关系,您还必须编译 date_time、线程、计时、文件系统和系统(只需将“--with-python”替换为“--with -otherlibname".)

  • 最后一步是确保您正在构建的扩展模块 link 是针对 "right" 库的。我发现定义预处理器符号 BOOST_DEBUG_PYTHON 和 BOOST_LINKING_PYTHON 以及预期的 _DEBUG 就足够了,因为在 config/auto_link.hpp 中有行
    #        if defined(_DEBUG) && defined(BOOST_DEBUG_PYTHON) && defined(BOOST_LINKING_PYTHON)
    #            define BOOST_LIB_RT_OPT "-gyd"
    #        elif defined(_DEBUG)
    #            define BOOST_LIB_RT_OPT "-gd"
    #        else
    #            define BOOST_LIB_RT_OPT
    #        endif

应该这样做 - Python 扩展模块的调试版本应该编译和 link 针对期望 link 的 Boost Python 库python35_d.lib,并且在由 python_d.exe.

调用的脚本加载时不会崩溃