php小編百草為你介紹如何使用gcc (mingw32)編譯帶有靜態庫的DLL。在開發過程中,經常需要將靜態庫打包成DLL以便于在其他項目中調用。使用gcc (mingw32)編譯帶有靜態庫的DLL的方法相對簡單,只需按照一定的步驟操作即可。首先,確保已安裝mingw32和gcc編譯器。然后,在命令行中輸入gcc -shared -o libname.dll libname.a即可生成DLL文件。通過這種方式,你可以輕松地將靜態庫編譯為DLL,以便在其他項目中使用。
問題內容
我有一個由外部工具(即 cgo)生成的靜態庫,我們將其稱為 libsecondary.a。我想生成一個動態庫,同時包含“libsecondary.a”作為依賴項,我在 libsecondary.h 中導出一個名為 onprocessinit() 的函數,并在 dll_process_attach 事件上調用它。
我嘗試生成共享庫,但似乎無法使用
x86_64-w64-mingw32-共享-l。 -lsecondary -static-libgcc -static-libstdc++ -static .\dllmain.c
錯誤輸出是
dllmain.c:(.text+0x9b): 未定義對“onprocessinit”的引用,這是怎么回事?
這是頭文件libsecondary.h
/* code generated by cmd/cgo; do not edit. */
/* package command-line-arguments */
#line 1 "cgo-builtin-export-prolog"
#include
#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
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
65be0f35ebbcbc
這是導出的 golang 函數(我使用 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() {}
登錄后復制
解決方法
哇,答案是論證位置,
x86_64-w64-mingw32 -shared -static-libgcc -static-libstdc++ -static .\dllmain.c .\libsecondary.a
如果你向后輸入它,它將找不到來自 libsecondary.a 的引用,天哪……
上面的代碼在加載時也會陷入死鎖,因為 syscall.NewLazyDLL 調用 LoadLibraryA,并且它被鎖定在 DLL_PROCESS_ATTACH 中,所以解決方法是 CreateThread 并在線程內運行 golang 導出函數:)






