【问题标题】:Link against a Windows .dll+.lib file combination with GCC under Cygwin?在 Cygwin 下使用 GCC 链接 Windows .dll+.lib 文件组合?
【发布时间】:2013-07-31 21:14:53
【问题描述】:

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

但如果我有

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

这些 DLL 来自其他方;我无权访问他们的源代码 - 但可以访问相应的包含文件,我可以根据这些文件进行编译。

【问题讨论】:

  • 使用.lib.dll文件的完整路径名,没有-L-l,只有文件名,如g++ -o foo.exe foo.o c:\something\somethingelse\some.lib。 (您也可以使用通常的 -L/-l 约定,但前提是库名称文件以 'lib' 开头,在 Windows 下通常不是这种情况)。
  • @n.m.:是这样吗,它没用……你确定它应该有用吗?
  • 为我工作。你遇到了什么错误?
  • 抱歉恢复这个问题,但我遇到了同样的问题,我尝试了不同的方法,包括你的建议@n.'pronouns'm。直接链接到lib文件。但我仍然收到“未定义的引用”错误。我正在使用由 qmake 和 mingw73_64 的 g++ 生成的 make
  • 只是补充一点 @n.18e9 是正确的,因为您必须使用 lib 文件的完整路径名,而不使用任何 -L 或 -l 选项。经过大量试验和错误,这是使用 x86_64-w64-mingw32/8.3.0 和 MSVC 生成的 lib 文件。此外,重要确保您链接到为 64 位平台(MSVC 目标 X64,而不是 Win32)生成的 lib 文件(和关联的 dll)。如果您尝试使用 32 位 lib 文件,g++ 似乎会忽略它并在您尝试所有组合时给您未定义的引用。

标签: c gcc dll linker cygwin


【解决方案1】:

如果您可以在 Cygwin 或 MinGW 中链接到 .lib,那么您可以(间接)链接到 DLL。

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

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

可以在 Cygwin 或 MinGW 中链接 .lib 文件。示例:

g++ -o myprg myprg.o -lShlwapi

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

链接到 DLL 的导入库的工作方式相同。

注意 1:请记住不同的 ABI 和名称修改。但是,在大多数情况下,调用 DLL 或 LIB 文件中的普通 C 函数是可行的。

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

【讨论】:

  • 这对我不起作用;我已经在这个问题上几天了,我无法得到解决方案。每当我链接库时,我都会收到“对...的未定义引用”错误
  • @DuckDodgers,你能说出 1-3 个未定义的符号吗?你链接的是哪个库?
  • 感谢您的回复。我正在链接到一个名为:HTUSB 的自定义库。我有静态和动态库,我试图链接到我的 c++ 程序。这是我的文件夹结构的图片:ibb.co/jf0xXHd。我将 dll 和 .lib 文件放在两个地方,以防文件夹结构成为问题。最后,这是我用来链接文件的命令:g++ decibel_test.cpp -I\Users\13122\OneDrive\Desktop\decibel -L"\Users\13122\OneDrive\Desktop\decibel\HTUSB.dll"。这是一个错误“未定义的对 `_imp__HTUSB_Close@0' 的引用”HTUSB_CLOSE 是库中的函数之一
  • 请检查导入库 (.lib) 是否导出给定符号。 (dumpbin 命令,或 cygwin 下的 nm)。还要确保名称修改(和调用约定)匹配,这可能是使用不同编译器(=不同 ABI)编译库的问题。
  • 首先感谢您一直以来的回复!其次,我运行“nm F HTUSB.lib”,我得到“没有这样的文件或目录”。但后来我运行“nm F HTUSB.dll”,我得到“无符号”。奇怪,因为 dll 文件肯定不是空的,而且 .lib 文件肯定存在。对不起,如果问题看起来很愚蠢;我是新手
【解决方案2】:

@einpoklum 将我的评论转换为答案:@n.18e9 是正确的,因为您必须使用不带任何 -L 或 -l 选项的 lib 文件的完整路径名。 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 DLL diXmlsq.dll 完全用纯 C 代码编写,并导出简单的 C 函数(外部“C”)。 特别是,对于本示例,它导出了一个返回整数值的XMLSQ_Gen_Version 函数。 DLL 是使用面向 X64 平台的 MSVC 12.0 编译的。 MSVC生成的关联库文件为diXmlsq.lib

我应该补充一点,这个 DLL 的工作方式与 Windows“Win32 API”DLL 完全相同,所以这里的说明应该适用于Windows\System32 中的标准 Windows 库(再次确保链接到 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"

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

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

diXmlsq.def

LIBRARY      "diXmlsq"
EXPORTS
    XMLSQ_Gen_Version

diXmlsq.h - diXmlsq.dll 的 C 接口

#ifdef __cplusplus
extern "C" {
#endif

long __stdcall XMLSQ_Gen_Version(void);

#ifdef __cplusplus
}
#endif

在纯 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;
}

示例 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"

C++ 接口的想法是成为普通 C 库的接口,使用更方便的 STL 类型,如 std::stringstd::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;
}

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();
    };
}

xmlsq.cpp - C++ 实现。

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

namespace xmlsq
{
    int Gen::Version() {
        int n = XMLSQ_Gen_Version();
        return n;
    }
}

示例 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

【讨论】:

  • 在我有时间研究这个问题之前,你的努力就得到了 +1 的评价:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-24
相关资源
最近更新 更多