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

时间:2013-12-10 02:27:41

标签: c++ visual-studio gcc dll dlltool

第1步。我的可执行文件( main.exe )有一个导入lib文件( main.lib ),用于导出一些符号。使用extern“C”导出的符号。

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

第3步。构建了一个dll( bbb.dll )链接到此库( extra.lib )以调用这些额外的功能来自 main.exe 。 (请注意 bbb.dll 首先由 main.exe 加载和使用。)

现在我尝试使用Mingw(gcc)而不是MS Visual Studio(cl)重复步骤2和3。我们称之为步骤2x和3x。 由于main.exe是一个包含许多文件的大项目......来自源代码的 libmain.a 构建不是一个好选择,我发现here 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'

这是一个名称差异问题吗?

或者甚至可以用这种方式使用gcc构建 bbb.dll 吗?

我做错了什么?

我在Windows 7上使用Visual Studio 2012. MinGW with gcc 4.6.1。

检查'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

1 个答案:

答案 0 :(得分:0)

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

虽然大主程序和额外的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"Debug\foo.pch" /Fa"Debug\" /Fo"Debug\" /Fd"Debug\vc100.pdb" /Gd /analyze- /errorReport:queue 
# linker; generate foo.lib
/OUT:"C:\svn_local\0\Users\mku\MinGW_w32\stackoverflow.com\20484904\trunk\msvc2010_build_foo_exe\foo\Debug\foo.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:"Debug\foo.exe.intermediate.manifest" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"C:\svn_local\0\Users\mku\MinGW_w32\stackoverflow.com\20484904\trunk\msvc2010_build_foo_exe\foo\Debug\foo.pdb" /SUBSYSTEM:CONSOLE /PGD:"C:\svn_local\0\Users\mku\MinGW_w32\stackoverflow.com\20484904\trunk\msvc2010_build_foo_exe\foo\Debug\foo.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 SP1Rel。

gcc 4.7.2

来自http://sourceforge.net/p/mingw/utils/ci/master/tree/reimp/

的reimp来源