使用GCC(MinGW32)编译依赖静态库的DLL遇链接错误求助
问题
我有一个CGO生成的静态库libsecondary.a,想基于它生成动态库,要求在DLL_PROCESS_ATTACH事件中调用libsecondary.h里导出的OnProcessInit()函数。
我用了这条编译命令:
x86_64-w64-mingw32 -shared -L. -lsecondary -static-libgcc -static-libstdc++ -static .\dllmain.c
但编译失败,错误提示:
dllmain.c:(.text+0x9b): undefined reference to `OnProcessInit'
相关文件内容
头文件libsecondary.h
/* Code generated by cmd/cgo; DO NOT EDIT. */ /* package command-line-arguments */ #line 1 "cgo-builtin-export-prolog" #include <stddef.h> #ifndef GO_CGO_EXPORT_PROLOGUE_H #define GO_CGO_EXPORT_PROLOGUE_H #ifndef GO_CGO_GOSTRING_TYPEDEF typedef struct { const char *p; ptrdiff_t n; } _GoString_; #endif #endif /* Start of preamble from import "C" comments. */ /* End of preamble from import "C" comments. */ /* Start of boilerplate cgo prologue. */ #line 1 "cgo-gcc-export-header-prolog" #ifndef GO_CGO_PROLOGUE_H #define GO_CGO_PROLOGUE_H typedef signed char GoInt8; typedef unsigned char GoUint8; typedef short GoInt16; typedef unsigned short GoUint16; typedef int GoInt32; typedef unsigned int GoUint32; typedef long long GoInt64; typedef unsigned long long GoUint64; typedef GoInt64 GoInt; typedef GoUint64 GoUint; typedef size_t GoUintptr; typedef float GoFloat32; typedef double GoFloat64; #ifdef _MSC_VER #include <complex.h> typedef _Fcomplex GoComplex64; typedef _Dcomplex GoComplex128; #else typedef float _Complex GoComplex64; typedef double _Complex GoComplex128; #endif /* static assertion to make sure the file is being used on architecture at least with matching size of GoInt. */ typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; #ifndef GO_CGO_GOSTRING_TYPEDEF typedef _GoString_ GoString; #endif typedef void *GoMap; typedef void *GoChan; typedef struct { void *t; void *v; } GoInterface; typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; #endif /* End of boilerplate cgo prologue. */ #ifdef __cplusplus extern "C" { #endif extern __declspec(dllexport) void OnProcessInit(); #ifdef __cplusplus } #endif
dllmain.c文件
#include <windows.h> #include <stdio.h> #include "libsecondary.h" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) { switch (fdwReason) { case DLL_PROCESS_ATTACH: printf("It works i guess"); OnProcessInit(); break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; } return TRUE; }
生成静态库的Go代码(用go build -buildmode=c-archive编译)
package main import "C" import ( "unsafe" "syscall" ) //export OnProcessInit func OnProcessInit() { const ( NULL = 0 MB_OK = 0 ) caption := "Hola" title := "desdegoo" ret, _, _ := syscall.NewLazyDLL("user32.dll").NewProc("MessageBoxW").Call( uintptr(NULL), uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(caption))), uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(title))), uintptr(MB_OK)) if ret != 1 { return } return } func main() {}
原因与解决方案
核心原因:链接库的顺序错误
MinGW链接器是按从左到右的顺序处理依赖的,你把静态库-lsecondary放在了源文件dllmain.c前面,导致链接器处理库的时候还不知道需要OnProcessInit这个符号,后续处理源文件时自然找不到该符号的定义。
修复步骤
调整编译命令的参数顺序:把源文件
dllmain.c放在链接库参数-lsecondary之前,让链接器先处理源文件,明确需要哪些符号,再从静态库中查找对应的定义。同时注意命令里要加上-gcc后缀,否则可能调用的不是编译器工具:x86_64-w64-mingw32-gcc -shared -L. -static-libgcc -static-libstdc++ -static .\dllmain.c -lsecondary额外注意事项:
- 确保
libsecondary.a和libsecondary.h都在当前目录下,或者用-L指定正确的库路径。 - Go生成的C静态库依赖Go运行时,
-static参数会把相关依赖静态链接进去,避免运行时找不到Go的动态库。
- 确保
内容的提问来源于stack exchange,提问作者Cuervo
相关产品推荐
相关产品推荐

