我的程式使用了一些包含 POSIX 函式呼叫并且不能用 MinGW 編譯的庫,我將 Qt6 用于 MinGW(沒有 Qt6 用于 cygwin 或 msys2)。所以我需要讓我的程式鏈接到由cygwin構建的dll。它鏈接成功,但無法運行。
例如,這里有兩個檔案a.c和b.c:
/* a.c */
int a() {
return 1;
}
/* b.c */
extern int a();
int main() {
return a();
}
我編譯a.c為a.dll使用 cygwin:
(In cygwin shell)
$ gcc -c a.c -o a.o
$ gcc -shared a.o -o a.dll
$ ldd a.dll
ntdll.dll => /cygdrive/c/Windows/SYSTEM32/ntdll.dll (0x7ff9d5450000)
KERNEL32.DLL => /cygdrive/c/Windows/System32/KERNEL32.DLL (0x7ff9d50f0000)
KERNELBASE.dll => /cygdrive/c/Windows/System32/KERNELBASE.dll (0x7ff9d2e90000)
msvcrt.dll => /cygdrive/c/Windows/System32/msvcrt.dll (0x7ff9d5370000)
cygwin1.dll => /cygdrive/c/Users/notify/Documents/cygwin1.dll (0x180040000)
advapi32.dll => /cygdrive/c/Windows/System32/advapi32.dll (0x7ff9d3b70000)
sechost.dll => /cygdrive/c/Windows/System32/sechost.dll (0x7ff9d3c20000)
RPCRT4.dll => /cygdrive/c/Windows/System32/RPCRT4.dll (0x7ff9d51b0000)
CRYPTBASE.DLL => /cygdrive/c/Windows/SYSTEM32/CRYPTBASE.DLL (0x7ff9d2440000)
bcryptPrimitives.dll => /cygdrive/c/Windows/System32/bcryptPrimitives.dll (0x7ff9d2b50000)
然后我使用 MinGW 編譯b.c并將其鏈接到a.dll:
(In MSYS2 MINGW64 shell)
$ gcc -c b.c -o b.o
$ gcc b.o -L. a.dll -o b.exe
$ ldd b.exe
ntdll.dll => /c/Windows/SYSTEM32/ntdll.dll (0x7ff9d5450000)
KERNEL32.DLL => /c/Windows/System32/KERNEL32.DLL (0x7ff9d50f0000)
KERNELBASE.dll => /c/Windows/System32/KERNELBASE.dll (0x7ff9d2e90000)
msvcrt.dll => /c/Windows/System32/msvcrt.dll (0x7ff9d5370000)
a.dll => /c/Users/notify/Documents/a.dll (0x5e4da0000)
cygwin1.dll => /c/Users/notify/Documents/cygwin1.dll (0x180040000)
$ ./b.exe
0 [main] b (1828) C:\Users\notify\Documents\b.exe: *** fatal error - cygheap base mismatch det
ected - 0x180350408/0x18034C408.
This problem is probably due to using incompatible versions of the cygwin DLL.
Search for cygwin1.dll using the Windows Start->Find/Search facility
and delete all but the most recent version. The most recent version *should*
reside in x:\cygwin\bin, where 'x' is the drive on which you have
installed the cygwin distribution. Rebooting is also suggested if you
are unable to find another cygwin DLL.
我怎么解決這個問題?
uj5u.com熱心網友回復:
回答
不要混合 MinGW 和 Cygwin 二進制檔案!
實際上,您應該將它們視為不同的模式:
- MinGW / MinGW-w64 針對原生 Windows
- Cygwin 不針對本機 Windows,而是使用 POSIX 兼容層。
它們的標準庫是不同的并且彼此不兼容。
這也適用于 MSVC,因此也不要將 MinGW / MinGW-w64 或 Cygwin 與 MSVC 混合。
解決方案
使用相同的編譯器編譯專案的所有組件和依賴項。
一些技巧
更喜歡 MinGW-w64
最好盡可能使用 MinGW / MinGW-w64,因為它針對的是原生 Windows。
論據:
- 當您想讓其他系統或人員可以使用 Cygwin 時,Cygwin 構建將需要與您的應用程式一起重新分發 Cygwin DLL。
- Cygwin 兼容層可能會導致開銷,因此您的應用程式的性能可能低于使用 MinGW / MinGW-w64 構建時的性能
最后:MinGW-w64 比 MinGW 更新,所以你應該使用 MinGW-w64 而不是 MinGW。MinGW-w64 支持 32 位和 64 位 Windows。您可以通過 MSYS2 的包管理器安裝 MinGW-w64 ,或者您可以從https://winlibs.com/pacman獲取獨立構建
MinGW / MinGW-w64 中缺少 POSIX 函式
使用 MinGW / MinGW-w64 的一個缺點是缺少一些 POSIX 函式(例如fork())。
所以你需要用他們的 Windows 替代品替換它們。
如果fork()它用于生成守護行程,您可能需要重新設計代碼的和平而不是尋找替代方案,fork()因為 Windows 不使用守護行程而是服務。因此,您需要為 Windows 撰寫一些特定于 Windows 的代碼,以允許您的應用程式作為 Windows 服務運行。您可以使用#ifdef _WIN32仍然將 POSIX 代碼保留在應用程式中,以便它仍然可以在 POSIX 平臺上編譯。
對于某些 POSIX 函式,已經有一些庫提供了具有兼容 C 標頭的 Windows 替代方案,例如:
dlfcn.h:https ://github.com/dlfcn-win32/dlfcn-win32sys/mman.h// : https://github.com/alitrack/mman-win32mmap()_munmap()fork():https://github.com/ieb/win32-fork
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/532238.html
標籤:C赛格温明威
