I have a Visual C++ project compiled using Visual Studio. This program imports 2 DLLs that I created using the MinGW x64 cross-compiler on Ubuntu. For this question, I have created 2 contrived DLLs containing bogus functions (these contrived DLLs still cause the same issue). We'll call these test1.dll
and test2.dll
.
test1.c
:
__declspec(dllexport) int test_func_add(int a, int b) { return a + b; }
__declspec(dllexport) unsigned long test_func_ptr(void* ptr_to_anything) { return (unsigned long)ptr_to_anything; }
test2.c
:
__declspec(dllexport) int test_func_mult(int a, int b) { return a * b; }
__declspec(dllexport) double test_func_div(double dividend, double divisor) { return dividend / divisor; }
Both of these C files are compiled using the exact same MinGW command:
x86_64-w64-mingw32-gcc test1.c -o test1.dll -shared -fvisibility=hidden -Wl,--out-implib,test1.lib
x86_64-w64-mingw32-gcc test2.c -o test2.dll -shared -fvisibility=hidden -Wl,--out-implib,test2.lib
Using dumpbin /exports
on the resulting test1.dll
and test2.dll
yields the following, respectively:
ordinal hint RVA name
// Look at the "Edit" section at the bottom of the question
1 0 000013D0 test_func_add
2 1 000013E4 test_func_ptr
ordinal hint RVA name
1 0 000013E3 test_func_div
2 1 000013D0 test_func_mult
And on the resulting import libraries (test1.lib
and test2.lib
, respectively):
ordinal name
// Look at the "Edit" section at the bottom of the question
test_func_ptr
test_func_add
ordinal name
test_func_mult
test_func_div
It seems like everything is fine?
However, when I link these DLLs into my Visual C++ application via their import libraries and run dumpbin /imports
on the resulting executable, I get this:
test1.dll
140021268 Import Address Table
1400C66C8 Import Name Table
0 time date stamp
0 Index of first forwarder reference
1 test_func_div
1 test_func_add
2 test_func_ptr
2 test_func_mult
test2.dll
140021268 Import Address Table
1400C66C8 Import Name Table
0 time date stamp
0 Index of first forwarder reference
1 test_func_div
1 test_func_add
2 test_func_ptr
2 test_func_mult
Its trying to import the same functions from both DLLs. Obviously, it then looks in one DLL for a function, doesn't find it, and throws an entry point could not be found error even though that function does exist - just in the other DLL.
Lastly, here's how I declared these external functions in the Visual C++ project:
extern "C" __declspec(dllimport) int test_func_add(int a, int b);
extern "C" __declspec(dllimport) unsigned long test_func_ptr(void* ptr_to_anything);
extern "C" __declspec(dllimport) int test_func_mult(int a, int b);
extern "C" __declspec(dllimport) double test_func_div(double dividend, double divisor);
Why could this be occuring? Are MinGW and MSVC projects incompatible? Is my process wrong? Any help would be much appreciated.
Edit: Looking back over the outputs of dumpbin /exports
, I noticed that the orderings of the functions are reversed on the import libraries when compared to their corresponding DLLs. Could this be part of the issue? I compared this to the orderings of opencv_world460.dll
and opencv_world460.lib
(my program uses OpenCV) and the orderings of the functions were the same in the import library and DLL.
By the way, I've already looked at this post. The OP had downloaded a different version import library than DLL, which doesn't answer my question as I created both the import library and DLL.
It turns out the problem did indeed have to do with the MinGW-generated import libraries. I solved the issue by using Microsoft's lib
tool to generate the import libraries instead. This requires telling the MinGW linker to output a .def
file, which can be done using the following command:
x86_64-w64-mingw32-gcc test1.c -o test1.dll -shared -fvisibility=hidden -Wl,--output-def,test1.def
x86_64-w64-mingw32-gcc test2.c -o test2.dll -shared -fvisibility=hidden -Wl,--output-def,test2.def
Then, in a Visual Studio terminal (after copying the .dll
and .def
files to Windows):
lib /DEF:test1.def /OUT:test1.lib /MACHINE:x64
lib /DEF:test2.def /OUT:test2.lib /MACHINE:x64
These commands will generate import libraries that actually work with the MSVC environment. To be clear, the dynamic libraries generated by MinGW were fine. It was only the import libraries that I needed to generate with official Microsoft tools.