使用从导入库(.lib)转换的库文件(.a),使用gcc构建dll



步骤1.我有一个可执行文件(main.exe)的导入lib文件(
main.lib。使用外部"C"导出的那些符号。

步骤2.我还有一个源文件(extra.cpp),它导出一些额外的函数。我从中生成了一个静态链接库(extra.lib),并将main.lib含在其中,因为这些额外的函数是从main.exe导出的用户。

步骤3。建立一个dll(bbb.dll),链接到此库(extra.libain.exe中的那些额外函数。(注意bbb.dll首先由main.exe加载和使用。)

现在,我尝试使用Mingw(gcc)而不是MSVisualStudio(cl)来重复步骤2和3。让我们称之为步骤2x和3x。由于main.exe是一个包含许多文件的大项目。。。从源代码构建libmain.a不是一个好的选择,我在这里发现main.lib可以使用以下命令转换为.a文件:

reimp -d main.lib
dlltool -k -d main.def -l libmain.a
# reimp creates the .def file. 
# dlltool uses the .def to create the .a that is linked in to the app. 

步骤2x

gcc -c -o extra.o -O1 -s -x c++ extra.cpp
ar rs libextra.a extra.o
ar rs libextra.a libmain.a

步骤3x

g++ -O2 -o bbb.dll -shared -x c++ bbb.cpp  -static-libgcc -static-libstdc++  -Wl,-s -Wl,--kill-at,--export-all-symbols,--enable-stdcall-fixup -Wl,--large-address-aware -lextra 

我在第3x步遇到链接器错误。

libmain.a(lextra.o):extra.cpp:(.text+0x38): undefined reference to `A_Function_In_main'

这是名称篡改差异问题吗

或者用这种方式构建bbb.dll是否可能

我做错了什么

我使用的是Windows 7上的Visual Studio 2012。具有gcc 4.6.1的MinGW。

检查"A_Function_In_main"是否在libmain.A:

nm libmain.a > libmain_dump.txt

libmain_dump.txt中关于"A_Function_in_main"的文本块

dshms00350.o:
00000000 b .bss
00000000 d .data
00000000 i .idata$4
00000000 i .idata$5
00000000 i .idata$6
00000000 i .idata$7
00000000 t .text
00000000 T A_Function_In_main
00000000 I __imp_A_Function_In_main
         U _head_libmain_a

有没有办法简化这个问题?

尽管大型主程序和额外的DLL之间似乎存在一些循环依赖关系,但我认为您只是在main中使用了一个回调函数。由于没有源代码或您正在使用的MSVC和gcc的相同版本,我的工作受到了阻碍。(我有MS Visual Studio 2010和mingw gcc-4.7.2)但问题的关键似乎是将MS生成的导入库转换为使用gcc。

或者,您可以通过调用LoadLibrary("bbb.dll"),然后使用GetProcAddress("A_Function_In_Main")来实现自己的导入库。但我想你的真实项目会让这种方法变得过于昂贵。

作为诊断,使用一个更简单的测试台测试reimp导入库:

foo.h

#ifdef FOO_DLL_EXPORTS
#define FOO_DLL_API __declspec(dllexport)
#else
#define FOO_DLL_API __declspec(dllimport)
#endif
extern "C" int FOO_DLL_API foo (int x);

foo.cpp

// define FOO_DLL_EXPORTS when building foo.cpp
#include "foo.h"
#include <iostream>
using std::cout;
using std::endl;
extern "C" int FOO_DLL_API foo (int x)
{
    return x + 1;
}
int main()
{
    cout << "foo.exe foo(1) returns " << foo(1) << endl; // expect 2
    return 0;
}

test.cpp

#include "foo.h"
#include <iostream>
using std::cout;
using std::endl;
int main()
{
    cout << "test.exe foo(3) returns " << foo(3) << endl; // expect 4
    return 0;
}

使用MSVC将foo.cpp编译为foo.exe并导入库foo.lib.

# compile foo.cpp; define FOO_DLL_EXPORTS
/ZI /nologo /W3 /WX- /Od /Oy- /D "FOO_DLL_EXPORTS" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Gm /EHsc /RTC1 /GS /fp:precise /Zc:wchar_t /Zc:forScope /Fp"Debugfoo.pch" /Fa"Debug" /Fo"Debug" /Fd"Debugvc100.pdb" /Gd /analyze- /errorReport:queue 
# linker; generate foo.lib
/OUT:"C:svn_localUsersmkuMinGW_w32stackoverflow.com20484904trunkmsvc2010_build_foo_exefooDebugfoo.exe" /INCREMENTAL /NOLOGO "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /MANIFEST /ManifestFile:"Debugfoo.exe.intermediate.manifest" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"C:svn_localUsersmkuMinGW_w32stackoverflow.com20484904trunkmsvc2010_build_foo_exefooDebugfoo.pdb" /SUBSYSTEM:CONSOLE /PGD:"C:svn_localUsersmkuMinGW_w32stackoverflow.com20484904trunkmsvc2010_build_foo_exefooDebugfoo.pgd" /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"foo.lib" /MACHINE:X86 /ERRORREPORT:QUEUE 

验证没有编译/链接错误。验证foo.exe返回代码是否为预期的2。

使用mingw-utils-reimp将foo.lib转换为libfoo.a,以便与gcc一起使用。(假设真正的foo.cpp无法重建,尽管在这个较小的例子中,foo.cpp可以用gcc-4.7.2重建)

reimp -d foo.lib
# reimp creates the foo.def file. 
dlltool -k -d foo.def -l libfoo.a
# dlltool uses the .def to create the .a that is linked in to the app. 

验证libfoo.a是否包含__imp_foo。

nm libfoo.a | grep __imp_foo
00000000 I __imp__foo

使用gcc使用导入库libfoo.a.将test.cpp编译为test.exe

g++.exe test.o  -o test.exe -static -static-libgcc -static-libstdc++ -L"C:/MinGW/lib"  /MinGW/lib/gcc/mingw32/4.7.2/libstdc++.a /MinGW/lib/gcc/mingw32/4.7.2/libgcc.a  libfoo.a

验证没有编译/链接错误。验证test.exe返回代码是否为预期的4。

这适用于我的系统。

Microsoft Visual Studio 2010版本10.0.40219.1 SP1修订版。

gcc 4.7.2

重新映射来源http://sourceforge.net/p/mingw/utils/ci/master/tree/reimp/

最新更新