Visual C++程序从错误的MinGW创建的DLL导入函数

pbpqsu0x  于 2023-08-03  发布在  其他
关注(0)|答案(1)|浏览(97)

我有一个使用Visual Studio编译的Visual C++项目。这个程序导入了我在Ubuntu上使用MinGW x64交叉编译器创建的2个DLL。对于这个问题,我创建了2个包含伪函数的人造DLL(这些人造DLL仍然会导致相同的问题)。我们将它们称为test1.dlltest2.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; }


这两个C文件都是使用完全相同的MinGW命令编译的:

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


在结果test1.dlltest2.dll上使用dumpbin /exports分别产生以下结果:

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


在生成的导入库(分别为test1.libtest2.lib)上:

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


好像一切都很好?
然而,当我通过导入库将这些DLL链接到Visual C++应用程序中,并在生成的可执行文件上运行dumpbin /imports时,我得到了以下结果:

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


它试图从两个DLL导入相同的函数。显然,它会在一个DLL中查找函数,但没有找到,并抛出一个入口点无法找到错误,即使该函数确实存在-只是在 * 其他 * DLL中。
最后,下面是我在Visual C++项目中声明这些外部函数的方式:

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);


为什么会发生这种情况?MinGW和MSVC项目是否不兼容?是我的过程错了吗?如果你能帮忙的话,我将不胜感激。

**编辑:**回顾dumpbin /exports的输出,我注意到导入库的函数顺序与其对应的DLL相比是 * 颠倒 * 的。这会是问题的一部分吗?我将其与opencv_world460.dllopencv_world460.lib(我的程序使用OpenCV)的顺序进行了比较,导入库和DLL中函数的顺序是相同的。

顺便说一下,我已经看过this post了。OP下载了一个与DLL不同版本的导入库,这并没有回答我的问题,因为我创建了导入库和DLL。

nhjlsmyf

nhjlsmyf1#

事实证明,这个问题确实与MinGW生成的导入库有关。我通过使用Microsoft的lib工具来生成导入库来解决这个问题。这需要告诉MinGW链接器输出一个.def文件,可以使用以下命令完成:

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

字符串
然后,在Visual Studio终端中(将.dll.def文件复制到Windows后):

lib /DEF:test1.def /OUT:test1.lib /MACHINE:x64
lib /DEF:test2.def /OUT:test2.lib /MACHINE:x64


这些命令将生成实际上与MSVC环境一起工作的导入库。需要说明的是,MinGW生成的动态库是很好的。我只需要使用官方的Microsoft工具生成导入库。

相关问题