65.9K
CodeProject 正在变化。 阅读更多。
Home

MinGW 静态和动态库

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.83/5 (29投票s)

2010 年 5 月 28 日

CPOL

4分钟阅读

viewsIcon

166346

downloadIcon

970

GCC 静态和动态库的简单介绍。

Objdump.PNG

引言

本文旨在对使用 MinGW (Minimal GNU for Windows) 编译器编译自己的库进行一个简短而简单的介绍。本文假设您对 C 语言有基本的了解。您需要做的第一件事是下载 MinGW。我强烈建议您将 Windows 环境变量设置为 MinGW 目录。这样您就可以从计算机上的任何目录调用 MinGW GCC 编译器。在 Windows 7 上,右键单击“我的电脑->属性->高级->环境变量”,然后将 MinGW 目录添加到 PATH,或者直接在 cmd.exe 中输入以下命令:

>SET PATH=%PATH%;C:\MinGW\bin

SET 将在命令提示符会话期间临时设置您的环境变量。如果您想永久更改环境变量,请使用 SETx 而不是 SET

静态库

以下代码用于创建静态库和动态库。这是一个简单的例子,用于演示一个可能的数学库。

add.c
#include "add.h"
int add(int a, int b) {
    return a + b;
}
add.h
#ifndef ADD_H
#define ADD_H
int add(int a, int b);
#endif  // ADD_H

主文件演示了如何在编译后调用库文件。请注意,您需要头文件或外部引用才能执行静态库。在大多数情况下,如果您共享您的库,它将以头文件的形式提供。函数声明对于链接器是必需的。如果您无法访问头文件,您将需要进行逆向工程来创建函数声明。

main.c
#include "add.h"
#include <stdio.h>
//extern int add(int a, int b);

int main() {
    int a = 2;
    int b = 1;
    printf("a=%d, b=%d\n", a,b);
    printf("add: %d\n", add(a,b));
    getchar();
    return 0;
}

编译静态库

static.png

构建库

>gcc -c add.c -o add.o
>ar rcs libadd.a add.o

gcc 标志:

  • -c: 禁用链接器调用
  • -o: 自定义输出文件

ar 标志:

  • -r: 将文件成员...插入存档(替换)。
  • -c: 表示您正在创建存档文件
  • -s: 将对象文件索引写入存档,更改将应用于存档

重要的是要认识到 GCC 编译器要求您在静态库前加上关键字 lib,后缀为 .a,例如 libadd.a。链接器需要 lib 前缀才能找到静态库。

引用库

>gcc -c main.c -o main.o
>gcc -c main.exe main.o -L. -ladd
>main.exe

gcc 标志:

  • -L: 指示您要引用的库的位置(. = 当前目录)
  • -l: 指定您要附加的特定库

编译动态库

动态库使用与之前完全相同的代码。大多数教程建议使用 __declspec(dllexport) 来导出函数引用。GCC 不需要这样做,因为 __declspec 是 Microsoft 特定的修饰符。其次,许多人将动态库视为 DLL(动态链接库);然而,GNU 将其动态库称为 so(共享对象)。尽管可以将共享库命名为 DLL 扩展名,但不建议这样做,因为 GCC 使用 ELF(可执行可链接格式),而 Microsoft Linker 使用 较旧的 COFF(通用对象文件格式)。通过将共享库命名为 so,您表明它是一个 GCC 共享库,而不是 Windows 特定的库。

dynamic.png

引用库

gcc -c add.c -o add.o
gcc -shared -o libadd.so add.o
gcc -o main.exe main.c libadd.so

gcc 标志:

  • -shared 告诉编译器您要编译一个共享库

请记住,您的 main.c 仍然需要访问 add.h 的头文件才能获取函数引用。否则,您必须手动将外部引用输入到主文件中。

静态与动态对比

staticVsDynamicErr.png

我首先注意到的是动态可执行文件比静态的可执行文件大。这是因为动态库具有引用动态库的开销。如果 DLL 包含大量函数,通常不会出现这种情况。由于 DLL 中只有一个函数,动态库的开销超过了对静态库的需求。在示例图像中,一旦删除了 DLL,动态可执行文件将无法运行,因为它依赖于动态库。静态库无需外部库即可执行,因为它们直接编译到可执行文件中。

动态

Pro

  • 多个可执行文件可以引用 DLL
  • 可执行文件通常更小
  • 代码集中,更新更轻松
  • 适合大型项目

缺点

  • 需要外部库

静态

Pro

  • 不依赖外部库
  • 适合小型项目或一次性写入项目

缺点

  • 可执行文件通常更大,因为机器码在文件中重复

结论

动态库和静态库在您的项目中都有其位置。请务必为正确的任务选择正确的库。请记住,无论库类型如何,您仍然需要头文件才能执行库中包含的函数。我发现使用 GCC 制作库通常更容易。请记住将您的静态库命名为 *.a,将共享库命名为 *.so,这样它们就不会被误认为是 Windows 特定的 *.lib*.dll 库。在我的下一篇文章中,我将介绍如何在 Microsoft Visual C++ 中生成库以及使用类。

历史

版本 1.0。

我的下一篇文章将解释如何使用 Microsoft Visual C++ 引用库。

© . All rights reserved.