pythonc++swiglinkageerror

CPP to Python using SWIG fails with "error LNK2001: unresolved external symbol"


I am trying to create the simplest cpp-to-python SWIG example.
I have one class (SwigTest), consisted of cpp and h files, with one public method in it swig_test_connection.
The swig wrapper generation (*.cxx and *.py files) works out of the box,
but when I try to build (using setup.py) I am getting a linkage error:
LINK : error LNK2001: unresolved external symbol PyInit__swig_test

See detailed re-production steps below.

I followed the instructions from:

I feel like I am missing something elementary here, so I will be grateful for any suggestion.

System details

I am using Windows 10, python 3.6.7 and VS 2019.
I also tried on a clean machine with Windows 10, python 3.6.7 and VS 2017 and got the same results.

Detailed Reproduce Steps

I created a single class (SwigTest) with one public member method in it swig_test_connection:

swig_test.h:

//// swig_test.h ////

#ifndef _SWIG_TEST_
#define _SWIG_TEST_

class SwigTest
{
public:
    int swig_test_connection();
};

#endif // !_SWIG_TEST_

swig_test.cpp:

//// swig_test.cpp ////

#include "swig_test.h"

int SwigTest::swig_test_connection() {
    return 32;
}

I also created a swigtest.i file:
swigtest.i

%module swig_test_module
%{
#include "swig_test.h"
%}

%include "swig_test.h"

I saved all those files under the same folder:

Next I created the SWIG wrapping files by running the following command:
swig -python -c++ swigtest.i

This generated 2 SWIG wrapper files:

swig_test_module.py
swigtest_wrap.cxx

The last step was to create setup.py:
setup.py

import os

from distutils.core import setup, Extension


swig_test_module = Extension(
    '_swig_test',
    sources=[
        os.path.join("swigtest_wrap.cxx"),
        os.path.join("swig_test.cpp")
    ]
)

setup(
    name="swig_test",
    version='0.1',
    author="Saar",
    description="""SWIG test""",
    py_modules=["swig_test_module"],
    ext_modules=[swig_test_module]
)

Finally, I tried to build the module:
python setup.py build_ext --inplace

This generated the following error:

LINK : error LNK2001: unresolved external symbol PyInit__swig_test

Full error stacktrace:

running build_ext
building '_swig_test' extension
creating build
creating build\temp.win-amd64-3.6
creating build\temp.win-amd64-3.6\Release
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\bin\HostX86\x64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MT -IC:\Projects\SwigTest\venv\include -IC:\Python367\include -IC:\Python367\include "-IC:\Program Files (x86)\Microsoft
Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\include" "-IC:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\ucrt" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\share
d" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\um" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\winrt" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\cppwinrt" /EHsc /Tpswigtest_wrap.cxx /Fobuild\temp.win-amd64-3
.6\Release\swigtest_wrap.obj
swigtest_wrap.cxx
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\bin\HostX86\x64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MT -IC:\Projects\SwigTest\venv\include -IC:\Python367\include -IC:\Python367\include "-IC:\Program Files (x86)\Microsoft
Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\include" "-IC:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\ucrt" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\share
d" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\um" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\winrt" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\cppwinrt" /EHsc /Tpswig_test.cpp /Fobuild\temp.win-amd64-3.6\R
elease\swig_test.obj
swig_test.cpp
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\bin\HostX86\x64\link.exe /nologo /INCREMENTAL:NO /LTCG /nodefaultlib:libucrt.lib ucrt.lib /DLL /MANIFEST:EMBED,ID=2 /MANIFESTUAC:NO /LIBPATH:C:\Projects\SwigTest\venv\libs /LIBP
ATH:C:\Python367\libs /LIBPATH:C:\Python367 /LIBPATH:C:\Projects\SwigTest\venv\PCbuild\amd64 "/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\lib\x64" "/LIBPATH:C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\lib\um
\x64" "/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.18362.0\ucrt\x64" "/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.18362.0\um\x64" /EXPORT:PyInit__swig_test build\temp.win-amd64-3.6\Release\swigtest_wrap.obj build\temp.win-amd64-3.6\Release
\swig_test.obj /OUT:C:\Projects\SwigTest\_swig_test.cp36-win_amd64.pyd /IMPLIB:build\temp.win-amd64-3.6\Release\_swig_test.cp36-win_amd64.lib
LINK : error LNK2001: unresolved external symbol PyInit__swig_test
build\temp.win-amd64-3.6\Release\_swig_test.cp36-win_amd64.lib : fatal error LNK1120: 1 unresolved externals
error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.26.28801\\bin\\HostX86\\x64\\link.exe' failed with exit status 1120

Any help would be greatly appreciated,
Thanks,
Saar


Solution

  • If someone encounters this issue, After too much time of debugging, the solution is very simple.

    The problem was that the name of the Extension declaration didn't match the name in py_modules in the setup call.

    Apparently it should be exactly the same name with leading underscore:

    import os
    
    from distutils.core import setup, Extension
    
    
    swig_test_module = Extension(
        '_swig_test_module',
        sources=[
            os.path.join("swigtest_wrap.cxx"),
            os.path.join("swig_test.cpp")
        ]
    )
    
    setup(
        name="swig_test",
        version='0.1',
        author="Saar",
        description="""SWIG test""",
        py_modules=["swig_test_module"],
        ext_modules=[swig_test_module]
    )