簡體   English   中英

如何讓MinGW編譯的程序鏈接到cygwin構建的dll?

[英]How to let MinGW compiled program link to dll built by cygwin?

我的程序使用了一些包含 POSIX function 調用的庫,並且無法使用 MinGW 進行編譯,我將 Qt6 用於 MinGW(沒有 Qt6 用於 cygwin 或 msys2)。 所以我需要讓我的程序鏈接到cygwin構建的dll。 鏈接成功,但無法運行。

例如,這里有兩個文件a.cb.c

/* a.c */
int a() {
  return 1;
}
/* b.c */
extern int a();

int main() {
  return a();
}

我使用 cygwin 將a.dll a.c

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

我怎么解決這個問題?

回答

不要混合使用 MinGW 和 Cygwin 二進制文件!

事實上,您應該將它們視為不同的平台:

  • MinGW / MinGW-w64 目標本機 Windows
  • Cygwin 不針對本機 Windows,而是使用 POSIX 兼容層。

它們的標准庫不同且彼此不兼容。

這也適用於 MSVC,因此也不要將 MinGW / MinGW-w64 或 Cygwin 與 MSVC 混合使用。

解決方案

使用相同的編譯器編譯項目的所有組件和依賴項。

一些技巧

更喜歡 MinGW-w64

最好盡可能使用 MinGW / MinGW-w64,因為它針對本機 Windows。

Arguments:

  • 當您想讓其他系統或人員使用它時,Cygwin 構建將需要與您的應用程序一起重新分發 Cygwin DLL。
  • Cygwin 兼容層可能會導致開銷,因此您的應用程序的性能可能低於使用 MinGW / MinGW-w64 構建時的性能

最后:MinGW-w64 比 MinGW 更新,因此您應該使用 MinGW-w64 而不是 MinGW。 MinGW-w64 支持 32 位和 64 位 Windows。您可以通過 MSYS2 的 package 管理器pacman安裝 MinGW-w64,或者您可以從https://winlibs.com/獲得獨立構建

MinGW / MinGW-w64 中缺少 POSIX 函數

使用 MinGW / MinGW-w64 的缺點是缺少一些 POSIX 函數(例如fork() )。

所以你需要用他們的 Windows 替代品替換它們。

fork()用於生成守護進程的情況下,您可能需要重新設計代碼的和平,而不是為fork()尋找替代方案,因為 Windows 不使用守護進程,而是使用服務。 因此,您需要為 Windows 編寫一些特定於 Windows 的代碼,以允許您的應用程序作為 Windows 服務運行。 您可以使用#ifdef _WIN32將您的 POSIX 代碼保留在您的應用程序中,這樣它仍然可以在 POSIX 平台上編譯。

對於某些 POSIX 函數,已經有一些庫提供 Windows 替代品和兼容的 C header,例如:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM