pythonc++windowsswigmingw-w64

SWIG doesn't work on Windows with MinGW-w64 when binding C++ and Python: DLL load failed while importing: The specified module could not be found


I am trying to bind C++ with Python on Windows using SWIG and MinGW-w64 g++. So far I got a factorial calculator function in C++:

// factorial.cpp
long fact(long num)
{
    if (num <= 1) return 1;
    return num * fact(num - 1);
}

This is my factorial.i:

%module factorial
%{
extern long fact(long num);
%}

extern long fact(long num);

I then use Command Prompt to build these:

swig -python -c++ factorial.i

This generates factorial_wrap.cxx and factorial.py. I then use MinGW-w64 g++ to build these:

g++ -c factorial.cpp
g++ -c -fpic factorial_wrap.cxx -IC:\Users\kritomas\AppData\Local\Programs\Python\Python38\include
g++ factorial.o factorial_wrap.o -LC:\Users\kritomas\AppData\Local\Programs\Python\Python38\libs -shared -lpython38 -o _factorial.pyd

So far no problem. The problem occurs when I then open up Python in Command Prompt and try to import these:

C:\Users\kritomas\Desktop>python
Python 3.8.10 (tags/v3.8.10:3d8993a, May  3 2021, 11:48:03) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import factorial
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\kritomas\Desktop\factorial.py", line 15, in <module>
    import _factorial
ImportError: DLL load failed while importing _factorial: The specified module could not be found.
>>>

Here's the error, as you can see above. I already tried Dependency Walker, that gave me 2 missing DLLs. After putting both of them into System32, it still happens. I already tried using extern "C" instead of extern:

%module factorial
%{
extern "C" long fact(long num);
%}

extern "C" long fact(long num);

It just straight up removes fact():

C:\Users\kritomas\Desktop>g++ factorial.o factorial_wrap.o -LC:\Users\kritomas\AppData\Local\Programs\Python\Python38\libs -shared -lpython38 -o _factorial.pyd
factorial_wrap.o:factorial_wrap.cxx:(.text+0x38d7): undefined reference to `fact'
collect2.exe: error: ld returned 1 exit status

I have the same issue with Python 3.9.7, the only reason why I downgraded to 3.8.10 is because it runs perfectly on my Linux Mint VM (which has Python 3.8.10), if instead of running:

g++ -c -fpic factorial_wrap.cxx -IC:\Users\kritomas\AppData\Local\Programs\Python\Python38\include
g++ factorial.o factorial_wrap.o -LC:\Users\kritomas\AppData\Local\Programs\Python\Python38\libs -shared -lpython38 -o _factorial.pyd

I run:

g++ -c -fpic factorial_wrap.cxx -I/usr/include/python3.8
g++ factorial.o factorial_wrap.o -shared -o _factorial.so

It works perfectly:

kritomas@kritomas-virtual-machine:~/Desktop$ python
Python 3.8.10 (default, Sep 28 2021, 16:10:42) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import factorial
>>> factorial.fact(5)
120

What am I doing wrong? Is there anything I am missing here? Please help me. Thanks in advance ;)


Solution

  • I met exactly the same problem after upgraded python to 3.9 on windows . After struggling for hours, I managed to solve it by manually copying some dlls from ***/mingw/bin/ where mingw32-g++ is found to where my ***.pyd is located. I'm sure that ***/mingw/bin/ has been appended to %PATH%, but don't know why python3.9 couldn't find it.