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

warning LNK4197: export 'PyInit_python_module_name' specified multiple times; using first specification

我创建了一些 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 模块。

如何解决这个问题,它会影响性能还是会在执行过程中出错。

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

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

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

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


当 Python 解释器加载 extension/dll 时,模块的初始化函数(例如 PyInit_Cython_Mod1)必须是 visible/exported.

Cython使用宏PyMODINIT_FUNC来标记init-function,定义为

#define PyMODINIT_FUNC Py_EXPORTED_SYMBOL PyObject*

Py_EXPORTED_SYMBOL 在 Windows 上被标记为 visible/exported:

#define Py_EXPORTED_SYMBOL __declspec(dllexport)

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

然而,可能由于历史原因,distutils 发挥安全作用,并通过 /EXPORT:-链接器选项导出 init-symbol,如 here:[=26 所示=]

...
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()
...

这次没有警告!