是否可以使用Cygwin下的gcc/g ++链接Windows .dll + .lib文件组合?

ein*_*ica 6 c dll linker gcc cygwin

我知道如何在Unix-ish上下文中链接库:如果我正在使用.a.so文件,我指定根搜索目录-L/my/path/to/lib/和我添加的libMylib -lMyLib.

但是,如果我有

  • a .dll(例如在Windows\System32目录中)?
  • a .dll(in Windows\System32)和a .lib(其他地方)?

这些DLL是由其他一方提出的; 我无法访问他们的源 - 但是可以访问相应的包含文件,我可以根据这些文件进行编译.

Man*_*ork 7

如果你可以链接.lib到Cygwin或MinGW,那么你可以(间接)链接DLL.

在MSVC世界中,与DLL一起创建导入库并不罕见.它是一个静态库(.lib),它加载DLL并包装DLL的接口.您只需调用(静态)导入库中的包装函数,并让导入库执行所有与DLL相关的操作.

  • 对于Windows API,WindowsSDK中有导入库.
  • 对于您自己的MSVC DLL,MSVC可以在您构建DLL时自动生成导入库.
  • 对于第三方DLL,您可以基于相应的头文件构建静态包装库.

可以链接.libCygwin或MinGW 中的文件.例:

g++ -o myprg myprg.o -lShlwapi
Run Code Online (Sandbox Code Playgroud)

这链接到Shlwapi.lib.(该库必须位于本地目录或链接器的库路径中.)

链接DLL的导入库的方式相同.

注1:请记住不同的ABI和名称管理.但是,在大多数情况下,在DLL或LIB文件中调用普通C函数将起作用.

注意2:请记住,g ++要求以正确的顺序指定库.


Dav*_*d I 6

@einpoklum 将我的评论转换为答案:@n.18e9 是正确的,因为您必须使用 lib 文件的完整路径名,而不使用任何 -L 或 -l 选项。 g++ -o foo.exe foo.o c:\something\somethingelse\some.lib。您还可以直接链接到 Windows DLL 文件g++ -o foo.exe foo.o c:\something\somethingelse\some.dll

重要- 确保链接到为64 位平台(在 MSVC 目标 X64 上,而不是 Win32 上)生成的 lib 文件(和关联的 dll)。

好吧,你想要一个例子,那么我们开始吧。

以下是使用 gcc/g++ 链接到导出纯 C 函数的 Windows 本机 DLL 的两个示例(此处在 Windows 10 上使用 x86_64-w64-mingw32/8.3.0)。

我使用我自己的免费 xmlsq 库作为示例https://www.cryptosys.net/xmlsq。您可以下载核心本机 DLL 以及下面引用的所有源代码。确保您使用 64 位 DLL。

本机 Windows DLLdiXmlsq.dll完全用纯 C 代码编写,并导出简单的 C 函数(extern“C”)。特别是,对于此示例,它导出一个XMLSQ_Gen_Version返回整数值的函数。该 DLL 是使用针对 X64 平台的 MSVC 12.0 编译的。MSVC 生成的关联库文件是diXmlsq.lib.

我应该补充一点,这个 DLL 的工作方式与 Windows“Win32 API”DLL 完全相同,因此此处的说明应该适用于标准 Windows 库Windows\System32(再次确保链接到 64 位版本)。

示例1。一个普通的 C 接口。

这两个命令在我的系统上编译时不会发出警告:

> gcc -o test-ver test-ver.c "C:\fullpath\to\x64\diXmlsq.lib"

> gcc -o test-ver test-ver.c "C:\fullpath\to\x64\diXmlsq.dll"
Run Code Online (Sandbox Code Playgroud)

diXmlsq.dll使用以下定义文件进行编译。(您也可以使用__declspec(dllexport)

参考:https://learn.microsoft.com/en-us/cpp/build/exporting-from-a-dll? view=msvc-160

diXmlsq.def

LIBRARY      "diXmlsq"
EXPORTS
    XMLSQ_Gen_Version
Run Code Online (Sandbox Code Playgroud)

diXmlsq.h- C 接口diXmlsq.dll

#ifdef __cplusplus
extern "C" {
#endif

long __stdcall XMLSQ_Gen_Version(void);

#ifdef __cplusplus
}
#endif
Run Code Online (Sandbox Code Playgroud)

要在纯 C 程序中调用核心函数:

test-ver.c

#include <stdio.h>
#include "diXmlsq.h"
int main(void)
{
    long n;
    n = XMLSQ_Gen_Version();
    printf("Version = %ld\n", n);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

示例2。C++ 接口。

这两个命令都使用 g++ 进行编译而不发出警告。

> g++ -o test-simple test-simple.cpp xmlsq.cpp "C:\fullpath\to\x64\diXmlsq.lib"

> g++ -o test-simple test-simple.cpp xmlsq.cpp "C:\fullpath\to\x64\diXmlsq.dll"
Run Code Online (Sandbox Code Playgroud)

C++ 接口的想法是成为使用更方便的 STL 类型(如std::string和)的普通 C 库的接口std::vector。为了简单起见,我们将仅演示该Gen::Version方法。

C++ 代码摘录如下:

test-simple.cpp- 一个测试 C++ 程序。

#include <iostream>
#include "xmlsq.hpp"
int main()
{
    std::cout << "xmlsq::Gen::Version=" << xmlsq::Gen::Version() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

xmlsq.hpp- C++接口

namespace xmlsq
{
    class Gen {
    private:
        Gen() {} // Static methods only, so hide constructor.
    public:
        /** Get version number of core diXmlsq DLL. */
        static int Version();
    };
}
Run Code Online (Sandbox Code Playgroud)

xmlsq.cpp- C++ 实现。

#include "diXmlsq.h"
#include "xmlsq.hpp"

namespace xmlsq
{
    int Gen::Version() {
        int n = XMLSQ_Gen_Version();
        return n;
    }
}
Run Code Online (Sandbox Code Playgroud)

示例3。尝试错误地链接到 32 位库。

> gcc -o test-ver test-ver.c "C:\fullpath\to\Win32\diXmlsq.lib"
C:/Strawberry/c/bin/../lib/gcc/x86_64-w64-mingw32/8.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: 
C:\Users\user\AppData\Local\Temp\cce27Dhl.o:test-ver.c:(.text+0xe): 
undefined reference to `XMLSQ_Gen_Version'
collect2.exe: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)