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

时间:2016-08-26 07:56:35

标签: python c python-c-api python-c-extension debug-mode

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

我使用过Python.org的AMD64 Web安装程序,但在链接中我得到了

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

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

这是故意的吗?我看到一个旧的错误报告似乎表明Stable ABI免于调试版本。 (这就是我在SO上发帖而不是提交错误报告的原因)

如果是故意的,是否可以与python35_d.lib和python35.lib链接,还是有另一种解决方法?

1 个答案:

答案 0 :(得分:4)

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

关键是Boost Python库需要链接Python的Release版本,即使它是Boost Python的调试版本。通过尝试链接依赖于Boost Python的扩展模块,Boost的

config/auto_link.hpp

将(默认情况下)创建链接依赖项 - 使用

#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

解决方案是构建特定版本的Boost库,专门链接到python35_d.lib。涉及几个步骤:

  • 运行'bootstrap.bat --with-python =“C:\ Program Files \ Python35”'
  • 在您的主目录中编辑user-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,thread,chrono,filesystem和system(只需将“--with-python”替换为“--with-otherlibname”。)

  • 最后一步是确保您正在构建的扩展模块链接到“右”库。我发现定义预处理器符号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扩展模块的调试版本,它应该编译并链接一个Boost Python库,它希望链接到python35_d.lib,并且当用python_d调用的脚本加载时不会崩溃。 EXE。