警告LNK4197:多次指定导出'PyInit_python_module_name';使用第一个规范

时间:2016-06-02 15:46:04

标签: python python-3.x visual-c++ cython

我创建了一些Cython个文件,并使用

将它们导入Python文件
import pyximport
pyximport.install()

import Cython_Mod1
import Cython_Mod2

当我运行py文件时,C编译器(VC++14)生成了以下错误

Cython_Mod1.obj : warning LNK4197: export 'PyInit_Cython_Mod1' specified multiple times; using first specification
每个Cython模块

如何修复此问题并影响性能或执行时可能出错。

2 个答案:

答案 0 :(得分:6)

LNK4197是一个警告,因此它不应该影响.c文件的编译,Cython可能只生成多次导出该函数的代码(为了好)原因,我假设)。

由于PyInit_<modname>负责初始化模块;如果您的模块初始化并正确导入,则没有问题。它不会影响性能和/或导致错误执行。

答案 1 :(得分:0)

@Jim的回答指出,这只是一个(相对良性的)警告,可以忽略。

但是,此答案提供了更多信息和解决方法。


Python解释器加载扩展名/ dll时,模块的init函数(例如PyInit_Cython_Mod1)必须可见/导出。

Cython使用宏PyMODINIT_FUNC标记初始化函数,该函数定义为

#define PyMODINIT_FUNC Py_EXPORTED_SYMBOL PyObject*

在Windows上将Py_EXPORTED_SYMBOL标记为可见/导出:

#define Py_EXPORTED_SYMBOL __declspec(dllexport)

因此,无需通过命令行中的链接器选项导出符号。

但是,可能由于历史原因,distutils可以安全运行,并且也可以通过/EXPORT:-linker选项导出初始化符号,如here所示:

...
export_opts = ["/EXPORT:" + sym for sym in (export_symbols or [])]
...

export_symbolsget_export_symbols计算得出:

def get_export_symbols(self, ext):
    """Return the list of symbols that a shared extension has to
    export.  This either uses 'ext.export_symbols' or, if it's not
    provided, "PyInit_" + module_name.  Only relevant on Windows, where
    the .pyd file (DLL) must export the module "PyInit_" function.
    """
    initfunc_name = "PyInit_" + ext.name.split('.')[-1]
    if initfunc_name not in ext.export_symbols:
        ext.export_symbols.append(initfunc_name)
    return ext.export_symbols

但是,由于我们不需要通过链接器选项导出任何符号,因此可以如下重写该方法:

from distutils.command.build_ext import build_ext
def get_export_symbols_fixed(self, ext):
    return []

# replace wrong version with the fixed:
build_ext.get_export_symbols = get_export_symbols_fixed

import pyximport
pyximport.install()
...

这次没有警告!