我正在尝试移植最初使用 MSVC 完成的旧 C .dll 库,该库使用 BEA Tuxedo 库来使用 MinGW。
我遇到了 MSVC 编译并链接一个文件但 MinGW 失败的情况。实际问题是在链接阶段。出现“未定义的引用”错误。
这是创建 dll 的最小示例:(tpsetunsol_test.c)
#include <atmi.h>
void __stdcall msghandler(char *pszMessage, long lMessageLen, long lFlags)
{
}
int Inittpsetunsol()
{
int ret = 0;
tpsetunsol(msghandler);
return ret;
}
这编译没有错误:
gcc -Wall -fexceptions -g -O2 -DWIN32 -DNDEBUG -D_WINDOWS -ID:/dev/tuxedo/include -o tpsetunsol_test.o -c tpsetunsol_test.c
错误来了:
dllwrap --export-all-symbols -LD:/dev/tuxedo/lib -k --output-lib test.lib --output-def test.def --enable-stdcall-fixup --add-stdcall-alias -o IAWS.dll tpsetunsol_test.o -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lwtuxws32
C:\MinGW\bin\dllwrap.exe: no export definition file provided.
Creating one, but that may not be what you want
tpsetunsol_test.o: In function `Inittpsetunsol':
d:\dev\tpsetunsol_test.c:13: undefined reference to `tpsetunsol'
collect2.exe: error: ld returned 1 exit status
C:\MinGW\bin\dllwrap.exe: C:\MinGW\bin\gcc exited with status 1
atmi.h 中的函数声明:
extern void (_TMDLLENTRY * _TMDLLENTRY tpsetunsol _((void (_TMDLLENTRY *)(char _TM_FAR *, long, long)))) _((char _TM_FAR *, long, long));
#define _TMDLLENTRY __stdcall
#define _TM_FAR
版本:
$ gcc -v
Using built-in specs.
COLLECT_GCC=C:\MinGW\bin\gcc.exe
COLLECT_LTO_WRAPPER=c:/mingw/bin/../libexec/gcc/mingw32/4.7.2/lto-wrapper.exe
Target: mingw32
Configured with: ../gcc-4.7.2/configure --enable- languages=c,c++,ada,fortran,objc,obj-c++ --disable-sjlj-exceptions --with-dwarf2 --enable-shared --enable-libgomp --disable-win32-registry --enable-libstdcxx-debug --disable-build-poststage1-with-cxx --enable-version-specific-runtime-libs --build=ming
w32 --prefix=/mingw
Thread model: win32
gcc version 4.7.2 (GCC)
编辑:我发现在 MSVC 和 GCC 创建的目标文件上使用 nm 符号 tpsetunsol 是不同的
查看 _tpsetunsol 符号,很明显 MSVC 和 GCC 产生不同的符号。
GCC 产生:U _tpsetunsol
和 MSVC:U _tpsetunsol@4
编辑:使用 Haroogan 的建议构建后的 nm 输出:
$ dllwrap --export-all-symbols -LD:/dev/tuxedo.64/lib --output-lib test.lib --output-def test.def -o IAWS.dll tpsetunsol_test.o -lwtuxws32_new
C:\MinGW\bin\dllwrap.exe: no export definition file provided.
Creating one, but that may not be what you want
tpsetunsol_test.o: In function `Inittpsetunsol':
d:\dev\IA/tpsetunsol_test.c:13: undefined reference to `tpsetunsol'
collect2.exe: error: ld returned 1 exit status
C:\MinGW\bin\dllwrap.exe: C:\MinGW\bin\gcc exited with status 1
$ nm tpsetunsol_test.o
00000000 b .bss
00000000 d .data
00000000 N .debug_abbrev
00000000 N .debug_aranges
00000000 N .debug_info
00000000 N .debug_line
00000000 N .debug_loc
00000000 r .eh_frame
00000000 t .text
00000004 T _Inittpsetunsol
00000000 T _msghandler@12
U _tpsetunsol
$ nm ../tuxedo.64/lib/libwtuxws32.a | grep -i tpsetuns
00000000 I __imp__tpsetunsol@4
00000000 T _tpsetunsol@4
gcc 预处理器 (-E) 的输出(仅声明了 tpsetunsol 行)
extern void (__attribute__((__stdcall__)) * __attribute__((__stdcall__)) tpsetunsol (void (__attribute__((__stdcall__)) *)(char *, long, long))) (char *, long, long);