我创建了一些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
模块。
如何修复此问题并影响性能或执行时可能出错。
答案 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_symbols
由get_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()
...
这次没有警告!