使用从导入库(.lib)转换的库文件(.a)构建具有gcc的dll [英] Building a dll with a gcc using a library file (.a) converted from import library (.lib)

查看:356
本文介绍了使用从导入库(.lib)转换的库文件(.a)构建具有gcc的dll的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



步骤2。我也有一个源文件( extra.cpp ),它会导出一些额外的函数。我从它生成一个静态链接库( extra.lib ),我包括 main.lib ,因为这些额外的函数是 main .exe 。dll( bbb.dll 此库( extra.lib )可从 main.exe 调用这些额外的函数。
(请注意 bbb.dll 在第一时间由 main.exe 加载并使用。)



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

  reimp -d main.lib 
dlltool -k -d main.def -l libmain.a
#reimp创建.def文件。
#dlltool使用.def创建链接到应用程序的.a。

步骤2x。


$ b b

  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):未定义引用`A_Function_In_main'

这是一个名称改变的区别问题吗



甚至可以建立 bbb.dll 使用gcc这种方式?



我在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

externCint FOO_DLL_API foo(int x);

foo.cpp

  //在构建foo.cpp时定义FOO_DLL_EXPORTS 

#includefoo.h
#include< iostream>
using std :: cout;
using std :: endl;

externCint 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

  #includefoo.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;定义FOO_DLL_EXPORTS 
/ ZI / nologo / W3 / WX- / Od / Oy- / DFOO_DLL_EXPORTS/ DWIN32/ D_DEBUG/ D_CONSOLE/ D_UNICODE/ DUNICODE / Gm / EHsc / RTC1 / GS / fp:precise / Zc:wchar_t / Zc:forScope /Fp\"Debug\foo.pch/ FaDebug \/ FoDebug \/ FdDebug \ 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 / NOLOGOkernel32.libuser32.libgdi32.libwinspool.libcomdlg32.libadvapi32.libshell32.libole32.lib oleup32.libuuid.libodbc32.libodbccp32.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


b $ b

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



使用mingw-utils reimp将foo.lib转换为libfoo.a以供gcc使用。 (假设真正的foo.cpp是不实际的重建,虽然在这个较小的例子中foo.cpp可以用gcc-4.7.2重建)

  reimp -d foo.lib 
#reimp创建foo.def文件。
dlltool -k -d foo.def -l libfoo.a
#dlltool使用.def创建链接到应用程序的.a。

验证libfoo.a是否包含__imp_foo。

  nm libfoo.a | grep __imp_foo 

00000000 I __imp__foo

使用gcc编译test.cpp test.exe的导入库libfoo.a。

  g ++。exe test.o -o test.exe -static -static- libgcc -static-libstdc ++ -LC:/ 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 V9.0.40219.1 SP1Rel。



gcc 4.7.2



href =http://sourceforge.net/p/mingw/utils/ci/master/tree/reimp/ =nofollow> http://sourceforge.net/p/mingw/utils/ci/master/ tree / reimp /


Step 1. I have an import lib file (main.lib) for my executable (main.exe) which exports some symbols. Those symbols exported using extern "C".

Step 2. I also have a source file (extra.cpp) which exports some extra functions. I generate a static linking library (extra.lib) from it, and I include main.lib into it as those extra functions are the users of exports from main.exe.

Step 3. A dll (bbb.dll) is built linking with this library (extra.lib) to call those extra functions from main.exe. (note that bbb.dll is loaded and used by main.exe in first place.)

Now I'm trying to repeat steps 2 and 3 using Mingw(gcc) instead of MS Visual Studio(cl). Let's call it Step 2x and 3x. Since main.exe is a big project with many files ... the building libmain.a from sources is not a good option, I found here that main.lib can be converted to .a file using following commands:

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. 

Step 2x.

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

Step 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 

I'm getting linker errors at step 3x.

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

Is it a name mangling difference problem?

Or is it even possible to build bbb.dll using gcc this way?

What do I do wrong?

I'm using Visual Studio 2012 on Windows 7. MinGW with gcc 4.6.1.

*Checking if 'A_Function_In_main' is in libmain.a:*

nm libmain.a > libmain_dump.txt

The block of text in libmain_dump.txt regarding '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

解决方案

Is there a way to simplify this question?

Although there seems to be some circular dependency between the big main program and the extra DLL, I assume you're just using a callback function within main. My efforts are hampered by not having source code or the same versions of MSVC and gcc you are using. (I have MS Visual Studio 2010 and mingw gcc-4.7.2) But the crux of the problem seems to be converting the MS generated import library to work with gcc.

Alternatively, you could implement your own import library by calling LoadLibrary("bbb.dll") and then use GetProcAddress("A_Function_In_Main"). But I assume your real project makes this approach prohibitively expensive.

As a diagnostic, test the reimp import library with a simpler test bench:

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

Use MSVC to compile foo.cpp into foo.exe and import library 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 

Verify no compile/link errors. Verify foo.exe return code is 2 as expected.

Use mingw-utils reimp to convert foo.lib into libfoo.a for use with gcc. (Assuming the real foo.cpp was impractical to rebuild, although in this smaller example foo.cpp can be rebuilt with 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. 

Verify libfoo.a contains __imp_foo.

nm libfoo.a | grep __imp_foo

00000000 I __imp__foo

Use gcc to compile test.cpp to test.exe with import library libfoo.a.

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

Verify no compile/link errors. Verify test.exe return code is 4 as expected.

This works on my system.

Microsoft Visual Studio 2010 Version 10.0.40219.1 SP1Rel.

gcc 4.7.2

reimp sources from http://sourceforge.net/p/mingw/utils/ci/master/tree/reimp/

这篇关于使用从导入库(.lib)转换的库文件(.a)构建具有gcc的dll的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆