我一直在尝试使用SWIG包装C代码以便在Python中使用。我在Windows 10平台上使用MSYS和MingGW。我写了一个小的测试库
#include "add.h"
double add(double a, double b)
{
double c = a+b;
return c;
}
与标题
#ifndef __ADD_H
#define __ADD_H
extern double add(double a, double b);
#endif
接口文件是testpackage.i
%module testpackage
%{
#include "add.h"
%}
double add(double, double);
然后编译
swig -python -py3 testpackage.i
gcc -c -Wall add.c add_wrap.c
gcc -shared add.o add_wrap.o -L/mingw64/lib -lpython3.9 -o _testpackage.pyd
一个小的python程序来测试:
import testpackage
x = 2.3
y = 5.6
z = testpackage.add(x,y)
print(z)
现在编译没有错误或警告和MSYS终端运行完美。(我还写了一些更复杂的多文件库,也工作得很好)python程序驻留在与生成的testpackage.py和_testpackage相同的目录中。pyd文件。但是,如果我尝试在Anaconda cmd或PowerShell终端中运行python脚本,或者如果我将其加载到Spyder中并从那里运行。我得到错误:
(base) C:msys64homehoylaswigHelloWorld>python test1.py
Traceback (most recent call last):
File "test1.py", line 1, in <module>
import testpackage
File "C:msys64homehoylaswigHelloWorldtestpackage.py", line 15, in <module>
import _testpackage
ImportError: DLL load failed while importing _testpackage: The specified module could not be found.
现在我知道的Python附带MinGW和运行MSYS终端是3.8.11 3.9.6而蟒蛇Python。这就是问题所在吗?如果是这种情况,我如何构建具有向后兼容性的库呢?还是我还漏掉了什么?
更新:设法在conda环境中安装3.9.6,但仍然找不到get模块-所以这不是问题!
进一步更新:运行Dependencies (x64)我发现_testpackage。pyd需要libPython3.9.dll (obvs -因为我链接了它!)。但是,在MSYS终端之外,由于文件夹不在PATH中,因此无法找到此文件夹。我将它添加到PATH中,依赖项执行器现在定位它,并且当我从Anaconda控制台运行时错误消息消失。然而,现在如果我导入testpackage模块,测试脚本崩溃,没有任何错误消息——要么运行我的test py脚本,要么导入交互式python——python只是退出。
经过一番苦闷之后,我终于找到了答案。MSYS/MinGW下的Python.exe是通过GCC编译的。查看从MSYS命令行启动python时的提示符:
$ python
Python 3.9.6 (default, Aug 15 2021, 14:43:38) [GCC UCRT 10.3.0 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
而来自Anaconda的python被编译成Microsoft C
python
Python 3.9.6 (default, Aug 18 2021, 15:44:49) [MSC v.1916 64 bit (AMD64)] :: Anaconda, Inc. on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
结果两个python exe被链接到不同的C运行时库。我在GCC下编译的模块/DLL链接到与MSYS python相同的模块/DLL,因此运行良好。但是当由Anaconda的python运行时,会导致运行库出现一些深度问题。
解决办法是编译(在GCC中在MSYS下)链接到Anaconda的python库,而不是MSYS的,所以从原始问题的链接步骤变成:
gcc -shared add.o add_wrap.o -L/c/Users/$(USERNAME)/Anaconda3/envs/$(ENVIRONMENT)/libs -lpython39 -o _testpackage.pyd
通常将$(USERNAME)替换为WIndows用户名,将$(ENVIRONMENT)替换为目标的Anaconda环境。L路径可能会有所不同,但基本上它是Anaconda环境的lib目录。请注意,anaconda中的库是python39,而MingGW中的库称为python3.9。我认为Anaconda是静态链接。但是这现在可以工作了,但是我只能为或Anaconda python或Mingw python构建,即使它们本质上是相同的版本。这似乎是一种痛苦-特别是如果我计划分发模块-幸运的是我没有!