如何让MinGW编译的程序链接到cygwin构建的dll?

6uxekuva  于 2022-12-03  发布在  其他
关注(0)|答案(1)|浏览(156)

我的程序使用了一些库,这些库包含POSIX函数调用,不能用MinGW编译,我用Qt6来编译MinGW(cygwin或msys2没有Qt6)。所以我需要让我的程序链接到cygwin创建的dll。链接成功,但无法运行。
例如,下面是两个文件a.cb.c
第一个
我使用cygwin将a.c编译为a.dll

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

我怎样才能解决这个问题?

wwwo4jvm

wwwo4jvm1#

答案

不要混合MinGW和Cygwin二进制文件!

实际上,您应该将它们视为不同的平台:

  • MinGW /MinGW-w 64以本机Windows为目标
  • Cygwin并不以原生Windows为目标,而是使用POSIX兼容层。

它们的标准库是不同的并且彼此不兼容。
这也适用于MSVC,所以也不要将MinGW /MinGW-w 64或Cygwin与MSVC混合。

溶液

使用相同的编译器编译项目的所有组件和依赖项。
一些提示

首选MinGW-w 64

最好尽可能使用MinGW /MinGW-w 64,因为它的目标是本机Windows。
参数:

  • 当你想让其他系统或人可以使用Cygwin时,Cygwin Build将需要重新发布Cygwin DLL沿着你应用程序。
  • Cygwin兼容层可能会导致开销,因此应用程序的性能可能会低于使用MinGW /MinGW-w 64构建时的性能

最后:MinGW-w 64比MinGW更新,所以您应该使用MinGW-w 64而不是MinGW。MinGW-w 64支持32位和64位Windows。您可以通过MSYS 2的软件包管理器pacman安装MinGW-w 64,或者您可以从https://winlibs.com/获得独立版本

MinGW /MinGW-w 64中缺少POSIX函数

使用MinGW /MinGW-w 64的缺点是缺少一些POSIX函数(例如fork())。
因此,您需要将它们替换为Windows替代品。
fork()的情况下,它被用来产生一个守护进程,你可能需要重新设计代码的和平比寻找一个替代fork()多一点,因为Windows不使用守护进程,但服务。所以你需要为Windows编写一些Windows特定的代码,让你的应用程序作为一个Windows服务运行。您可以使用#ifdef _WIN32将POSIX代码保留在应用程序中,以便它仍然可以在POSIX平台上编译。
对于一些POSIX函数,已经有一些库提供了带有兼容C头文件的Windows替代品,例如:

相关问题