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

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

问题描述

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

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".

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

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.

步骤3。一个dll( bbb.dll )与这个库( extra.lib )从 main.exe 调用这些额外的函数。
(请注意, bbb.dll 是首先由 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.)

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

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. 

步骤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处获取链接器错误。

I'm getting linker errors at step 3x.

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

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

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

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

我做错了什么?

我在Windows 7上使用Visual Studio 2012.GenGW与gcc 4.6.1。

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

检查'A_Function_In_main'是否在libmain.a中:

Checking if 'A_Function_In_main' is in libmain.a:

nm libmain.a > libmain_dump.txt

libmain_dump.txt中有关A_Function_In_main的文本块

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?

尽管在大主程序和额外的DLL之间似乎有一些循环依赖,我假设你只是在main中使用一个回调函数。我的努力受到没有使用源代码或MSVC和gcc的相同版本的阻碍。 (我有MS Visual Studio 2010和mingw gcc-4.7.2)但问题的症结似乎是将MS生成的导入库转换为使用gcc。

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.

或者,您可以通过调用LoadLibrary(bbb.dll)来实现自己的导入库,然后使用GetProcAddress(A_Function_In_Main)。但是我假设你的真正的项目使得这个方法价格昂贵。

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.

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

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

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

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 

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

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

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

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. 

验证libfoo.a包含__imp_foo。

Verify libfoo.a contains __imp_foo.

nm libfoo.a | grep __imp_foo

00000000 I __imp__foo

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

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

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

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

这在我的系统上有效。

Microsoft Visual Studio 2010版本10.0.40219.1 SP1Rel。

Microsoft Visual Studio 2010 Version 10.0.40219.1 SP1Rel.

gcc 4.7.2

gcc 4.7.2

http://sourceforge.net/p/mingw/utils/ci/master/树/ reimp /

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

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