CodeBlocks静态链接与动态链接设置

本文详细介绍了静态库和动态库的区别,包括静态库在编译时将函数链接到可执行文件,不依赖外部文件,但占用空间较大。动态库则在运行时链接,节省资源,便于升级。此外,文章还探讨了DLL地狱问题以及如何在CodeBlocks+GCC环境中设置静态和动态链接库。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

静态库和动态库的区别

1.静态库

之所以称之为”静态库”,是因为在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接。
从本质上来说,一个静态库可以简单看成是一组目标文件(.o/.obj文件)的集合,静态库与汇编生成的目标文件(.o/.obj)一起链接为可执行文件。
静态库(后缀为.a/.lib)和.o文件格式相似。即很多目标文件经过压缩打包后形成的一个文件
静态库特点总结:
1. 静态库对函数库的链接是放在编译时期完成的
2. 程序在运行时与函数库再无瓜葛,移植方便,因为代码已经嵌入到程序里面了,可以直接跟着程序走,不存在对外部文件的依赖
3. 浪费空间和资源,因为所有相关的目标文件与牵涉到的函数库被链接合成一个可执行文件,会增加原本程序的空间

GCC编译、使用静态库
静态库的后缀是.a(并没有强制规定),它的产生分两步
1. 由源文件编译生成一堆.o,每个.o里都包含这个编译单元的符号表
2. ar命令将很多.o转换成.a,成为静态库,从这点也可以看出来,库是很多.o文件的集合

编译好静态库文件之后,我们就可以在其他程序中使用静态库文件中的函数了
1. 只需要在使用到这些公用函数的源程序中包含这些公用函数的原型声明(include对应的头文件)
2. 然后在用gcc命令生成目标文件时指明静态库名
3. gcc将会从静态库中将公用函数连接到目标文件中
4. 注意,gcc会在静态库名前加上前缀lib,然后追加扩展名.a得到的静态库文件名来查找静态库文件,因此,我们在写需要连接的库时,只写名字就可以,如libhello.a的库,只写: -lhello

2.动态库

动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀lib,但其文件扩展名为.so(.dll)。例如:我们将创建的动态库名为myhello,则动态库文件名就是libmyhello.so。
使用库是重用代码的一种绝佳方式。 您不必在自己创建的每个程序中重新实现同一例程,而只需对这些例程写入一次,然后从需要该功能的应用程序引用它们即可。 通过将代码放入 DLL,您节省在引用它的每个应用程序的空间,而且,您可以更新 DLL,而无需重新编译所有应用程序。
动态链接库 (DLL) 是作为共享函数库的可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。DLL 还有助于共享数据和资源。多个应用程序可同时访问内存中单个 DLL 副本的内容。
动态链接与静态链接的不同之处在于它允许可执行模块(.dll 文件或 .exe 文件)仅包含在运行时定位 DLL 函数的可执行代码所需的信息。在静态链接中,链接器从静态链接库获取所有被引用的函数,并将库同代码一起放到可执行文件中。
使用动态链接代替静态链接有若干优点。DLL 节省内存,减少交换操作,节省磁盘空间,更易于升级,提供售后支持,提供扩展 MFC 库类的机制,支持多语言程序,并使国际版本的创建轻松完成。
DLL 的类型
当您在应用程序中加载 DLL 时,可以使用两种链接方法来调用导出的 DLL 函数。这两种链接方法是加载时动态链接和运行时动态链接。
动态库一般会有对应的导入库,方便程序静态载入动态链接库,否则你可能就需要自己LoadLibary调入DLL文件,然后再手工GetProcAddress获得对应函数了。有了导入库,你只需要链接导入库后按照头文件函数接口的声明调用函数就可以了。
加载时动态链接(load-time dynamic linking)
在加载时动态链接中,应用程序像调用本地函数一样对导出的 DLL 函数进行显式调用。要使用加载时动态链接,请在编译和链接应用程序时提供头文件 (.h) 和导入库文件 (.lib)。当您这样做时,链接器将向系统提供加载 DLL 所需的信息,并在加载时解析导出的 DLL 函数的位置。
运行时动态链接(run-time dynamic linking)
在运行时动态链接中,应用程序调用 LoadLibrary 函数或 LoadLibraryEx 函数以在运行时加载 DLL。成功加载 DLL 后,可以使用 GetProcAddress 函数获得要调用的导出的 DLL 函数的地址。在使用运行时动态链接时,无需使用导入库文件。

所谓静态、动态是指”链接”的过程存在区别:

3. DLL地狱

DLL地狱(DLL Hell)指在Microsoft Windows系统中,因为动态链接库(DLL)的版本或兼容性的问题而造成程序无法正常运行。
Windows早期并没有很严谨的DLL版本管理机制,以致经常发生安装了某软件后,因为其覆盖了系统上原有的同一个DLL文件,而导致原有可运行的程序无法运行。但还原回原有的DLL文件之后,所新安装的软件就无法运行。若覆盖到系统所使用的重要DLL时亦可能让系统容易死机甚至无法正常启动。
在CodeBlocks+GCC环境下,静态链接与动态链接设置如下:

静态链接

1.建立静态链接库

示例:
建立静态链接库工程,工程文件包括static.h和static.cpp,具体如下,然后编译工程,会生成一个libStaticLibrary.a文件。
libStaticLibrary.a是用于链接的,与其他文件一起编译生成一个exe执行文件。
static.h

#ifndef STATIC_H_INCLUDED  
#define STATIC_H_INCLUDED  

#ifdef __cplusplus  
extern "C"  
{  
#endif  

int SampleAddInt(int i1, int i2);  
void SampleFunction1();  
int SampleFunction2();  

#ifdef __cplusplus  
}  
#endif  

#endif // STATIC_H_INCLUDED  

static.cpp

#include "static.h"  

// A function adding two integers and returning the result  
int SampleAddInt(int i1, int i2)  
{  
    return i1 + i2;  
}  

// A function doing nothing ;)  
void SampleFunction1()  
{  
    // insert code here  
}  

// A function always returning zero  
int SampleFunction2()  
{  
    // insert code here  

    return 0;  
}  

2.建立主工程

建立Console application,将生成一个main.cpp示例文件,在最上方添加#include “static.h”语句,这样就可以调用静态链接库里的函数了。
main.cpp

#include <iostream>  
#include "static.h"  
using namespace std;  

int main()  
{  
    int a=1,b=2;  
    cout << "a + b = "<<SampleAddInt(a,b)<< endl;  
    return 0;  
}  

然后选择菜单栏Project->Build Options,弹出Project Build Options,选择工程名称。在Linker settings选项卡下添加libStaticLibrary.a的路径,即添加需要的库。在Search
directories选项卡下的Compiler子选项卡下添加static.h所在的目录路径,即写入项目的头文件目录。最后,点击编译即可。

动态链接

1.建立动态链接库

示例:
建立动态链接库工程,工程文件包括dynamic.h和dynamic.cpp,具体如下,然后编译工程,会生成一个libDynamicLibrary.a文件和DynamicLibrary.dll文件。
libDynamicLibrary.a是用于链接的,DynamicLibrary.dll用于与将要链接的exe执行文件一起工作。
dynamic.h

#ifndef __DYNAMIC_H__  
#define __DYNAMIC_H__  

#include <windows.h>  

/*  To use this exported function of dll, include this header 
 *  in your project. 
 */  

#ifdef BUILD_DLL  
    #define DLL_EXPORT __declspec(dllexport)  
#else  
    #define DLL_EXPORT __declspec(dllimport)  
#endif  


#ifdef __cplusplus  
extern "C"  
{  
#endif  

void DLL_EXPORT SomeFunction(const LPCSTR sometext);  

#ifdef __cplusplus  
}  
#endif  

#endif // __DYNAMIC__  

dynamic.cpp

#include "dynamic.h"  

// a sample exported function  
void DLL_EXPORT SomeFunction(const LPCSTR sometext)  
{  
    MessageBoxA(0, sometext, "DLL Message", MB_OK | MB_ICONINFORMATION);  
}  

extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)  
{  
    switch (fdwReason)  
    {  
        case DLL_PROCESS_ATTACH:  
            // attach to process  
            // return FALSE to fail DLL load  
            break;  

        case DLL_PROCESS_DETACH:  
            // detach from process  
            break;  

        case DLL_THREAD_ATTACH:  
            // attach to thread  
            break;  

        case DLL_THREAD_DETACH:  
            // detach from thread  
            break;  
    }  
    return TRUE; // succesful  
}  

2.建立主工程

建立win32 GUI project,将生成一个main.cpp示例文件,在最上方添加include “dynamic.h”语句,这样就可以调用动态链接库里的函数了。
main.cpp

静态库和动态库的区别

1.静态库

之所以称之为”静态库”,是因为在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接。
从本质上来说,一个静态库可以简单看成是一组目标文件(.o/.obj文件)的集合,静态库与汇编生成的目标文件(.o/.obj)一起链接为可执行文件。
静态库(后缀为.a/.lib)和.o文件格式相似。即很多目标文件经过压缩打包后形成的一个文件
静态库特点总结:
1. 静态库对函数库的链接是放在编译时期完成的
2. 程序在运行时与函数库再无瓜葛,移植方便,因为代码已经嵌入到程序里面了,可以直接跟着程序走,不存在对外部文件的依赖
3. 浪费空间和资源,因为所有相关的目标文件与牵涉到的函数库被链接合成一个可执行文件,会增加原本程序的空间

GCC编译、使用静态库
静态库的后缀是.a(并没有强制规定),它的产生分两步
1. 由源文件编译生成一堆.o,每个.o里都包含这个编译单元的符号表
2. ar命令将很多.o转换成.a,成为静态库,从这点也可以看出来,库是很多.o文件的集合

编译好静态库文件之后,我们就可以在其他程序中使用静态库文件中的函数了
1. 只需要在使用到这些公用函数的源程序中包含这些公用函数的原型声明(include对应的头文件)
2. 然后在用gcc命令生成目标文件时指明静态库名
3. gcc将会从静态库中将公用函数连接到目标文件中
4. 注意,gcc会在静态库名前加上前缀lib,然后追加扩展名.a得到的静态库文件名来查找静态库文件,因此,我们在写需要连接的库时,只写名字就可以,如libhello.a的库,只写: -lhello

2.动态库

动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀lib,但其文件扩展名为.so(.dll)。例如:我们将创建的动态库名为myhello,则动态库文件名就是libmyhello.so。
使用库是重用代码的一种绝佳方式。 您不必在自己创建的每个程序中重新实现同一例程,而只需对这些例程写入一次,然后从需要该功能的应用程序引用它们即可。 通过将代码放入 DLL,您节省在引用它的每个应用程序的空间,而且,您可以更新 DLL,而无需重新编译所有应用程序。
动态链接库 (DLL) 是作为共享函数库的可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。DLL 还有助于共享数据和资源。多个应用程序可同时访问内存中单个 DLL 副本的内容。
动态链接与静态链接的不同之处在于它允许可执行模块(.dll 文件或 .exe 文件)仅包含在运行时定位 DLL 函数的可执行代码所需的信息。在静态链接中,链接器从静态链接库获取所有被引用的函数,并将库同代码一起放到可执行文件中。
使用动态链接代替静态链接有若干优点。DLL 节省内存,减少交换操作,节省磁盘空间,更易于升级,提供售后支持,提供扩展 MFC 库类的机制,支持多语言程序,并使国际版本的创建轻松完成。
DLL 的类型
当您在应用程序中加载 DLL 时,可以使用两种链接方法来调用导出的 DLL 函数。这两种链接方法是加载时动态链接和运行时动态链接。
动态库一般会有对应的导入库,方便程序静态载入动态链接库,否则你可能就需要自己LoadLibary调入DLL文件,然后再手工GetProcAddress获得对应函数了。有了导入库,你只需要链接导入库后按照头文件函数接口的声明调用函数就可以了。
加载时动态链接(load-time dynamic linking)
在加载时动态链接中,应用程序像调用本地函数一样对导出的 DLL 函数进行显式调用。要使用加载时动态链接,请在编译和链接应用程序时提供头文件 (.h) 和导入库文件 (.lib)。当您这样做时,链接器将向系统提供加载 DLL 所需的信息,并在加载时解析导出的 DLL 函数的位置。
运行时动态链接(run-time dynamic linking)
在运行时动态链接中,应用程序调用 LoadLibrary 函数或 LoadLibraryEx 函数以在运行时加载 DLL。成功加载 DLL 后,可以使用 GetProcAddress 函数获得要调用的导出的 DLL 函数的地址。在使用运行时动态链接时,无需使用导入库文件。

所谓静态、动态是指”链接”的过程存在区别:

3. DLL地狱

DLL地狱(DLL Hell)指在Microsoft Windows系统中,因为动态链接库(DLL)的版本或兼容性的问题而造成程序无法正常运行。
Windows早期并没有很严谨的DLL版本管理机制,以致经常发生安装了某软件后,因为其覆盖了系统上原有的同一个DLL文件,而导致原有可运行的程序无法运行。但还原回原有的DLL文件之后,所新安装的软件就无法运行。若覆盖到系统所使用的重要DLL时亦可能让系统容易死机甚至无法正常启动。
在CodeBlocks+GCC环境下,静态链接与动态链接设置如下:

静态链接

1.建立静态链接库

示例:
建立静态链接库工程,工程文件包括static.h和static.cpp,具体如下,然后编译工程,会生成一个libStaticLibrary.a文件。
libStaticLibrary.a是用于链接的,与其他文件一起编译生成一个exe执行文件。
static.h

#ifndef STATIC_H_INCLUDED  
#define STATIC_H_INCLUDED  

#ifdef __cplusplus  
extern "C"  
{  
#endif  

int SampleAddInt(int i1, int i2);  
void SampleFunction1();  
int SampleFunction2();  

#ifdef __cplusplus  
}  
#endif  

#endif // STATIC_H_INCLUDED  

static.cpp

#include "static.h"  

// A function adding two integers and returning the result  
int SampleAddInt(int i1, int i2)  
{  
    return i1 + i2;  
}  

// A function doing nothing ;)  
void SampleFunction1()  
{  
    // insert code here  
}  

// A function always returning zero  
int SampleFunction2()  
{  
    // insert code here  

    return 0;  
}  

2.建立主工程

建立Console application,将生成一个main.cpp示例文件,在最上方添加#include “static.h”语句,这样就可以调用静态链接库里的函数了。
main.cpp

#include <iostream>  
#include "static.h"  
using namespace std;  

int main()  
{  
    int a=1,b=2;  
    cout << "a + b = "<<SampleAddInt(a,b)<< endl;  
    return 0;  
}  

然后选择菜单栏Project->Build Options,弹出Project Build Options,选择工程名称。在Linker settings选项卡下添加libStaticLibrary.a的路径,即添加需要的库。在Search
directories选项卡下的Compiler子选项卡下添加static.h所在的目录路径,即写入项目的头文件目录。最后,点击编译即可。

动态链接

1.建立动态链接库

示例:
建立动态链接库工程,工程文件包括dynamic.h和dynamic.cpp,具体如下,然后编译工程,会生成一个libDynamicLibrary.a文件和DynamicLibrary.dll文件。
libDynamicLibrary.a是用于链接的,DynamicLibrary.dll用于与将要链接的exe执行文件一起工作。
dynamic.h

#ifndef __DYNAMIC_H__  
#define __DYNAMIC_H__  

#include <windows.h>  

/*  To use this exported function of dll, include this header 
 *  in your project. 
 */  

#ifdef BUILD_DLL  
    #define DLL_EXPORT __declspec(dllexport)  
#else  
    #define DLL_EXPORT __declspec(dllimport)  
#endif  


#ifdef __cplusplus  
extern "C"  
{  
#endif  

void DLL_EXPORT SomeFunction(const LPCSTR sometext);  

#ifdef __cplusplus  
}  
#endif  

#endif // __DYNAMIC__  

dynamic.cpp

#include "dynamic.h"  

// a sample exported function  
void DLL_EXPORT SomeFunction(const LPCSTR sometext)  
{  
    MessageBoxA(0, sometext, "DLL Message", MB_OK | MB_ICONINFORMATION);  
}  

extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)  
{  
    switch (fdwReason)  
    {  
        case DLL_PROCESS_ATTACH:  
            // attach to process  
            // return FALSE to fail DLL load  
            break;  

        case DLL_PROCESS_DETACH:  
            // detach from process  
            break;  

        case DLL_THREAD_ATTACH:  
            // attach to thread  
            break;  

        case DLL_THREAD_DETACH:  
            // detach from thread  
            break;  
    }  
    return TRUE; // succesful  
}  

2.建立主工程

建立win32 GUI project,将生成一个main.cpp示例文件,在最上方添加include “dynamic.h”语句,这样就可以调用动态链接库里的函数了。
main.cpp

#include <windows.h>  

#include "dynamic.h"  

/*  Declare Windows procedure  */  
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);  

/*  Make the class name into a global variable  */  
char szClassName[ ] = "CodeBlocksWindowsApp";  

int WINAPI WinMain (HINSTANCE hThisInstance,  
                     HINSTANCE hPrevInstance,  
                     LPSTR lpszArgument,  
                     int nCmdShow)  
{  
    HWND hwnd;               /* This is the handle for our window */  
    MSG messages;            /* Here messages to the application are saved */  
    WNDCLASSEX wincl;        /* Data structure for the windowclass */  

    /* The Window structure */  
    wincl.hInstance = hThisInstance;  
    wincl.lpszClassName = szClassName;  
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */  
    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */  
    wincl.cbSize = sizeof (WNDCLASSEX);  

    /* Use default icon and mouse-pointer */  
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);  
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);  
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);  
    wincl.lpszMenuName = NULL;                 /* No menu */  
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */  
    wincl.cbWndExtra = 0;                      /* structure or the window instance */  
    /* Use Windows's default colour as the background of the window */  
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;  

    /* Register the window class, and if it fails quit the program */  
    if (!RegisterClassEx (&wincl))  
        return 0;  

    /* The class is registered, let's create the program*/  
    hwnd = CreateWindowEx (  
           0,                   /* Extended possibilites for variation */  
           szClassName,         /* Classname */  
           "Code::Blocks Template Windows App",       /* Title Text */  
           WS_OVERLAPPEDWINDOW, /* default window */  
           CW_USEDEFAULT,       /* Windows decides the position */  
           CW_USEDEFAULT,       /* where the window ends up on the screen */  
           544,                 /* The programs width */  
           375,                 /* and height in pixels */  
           HWND_DESKTOP,        /* The window is a child-window to desktop */  
           NULL,                /* No menu */  
           hThisInstance,       /* Program Instance handler */  
           NULL                 /* No Window Creation data */  
           );  

    /* Make the window visible on the screen */  
    ShowWindow (hwnd, nCmdShow);  

    SomeFunction("Dynamic Tester");  

    /* Run the message loop. It will run until GetMessage() returns 0 */  
    while (GetMessage (&messages, NULL, 0, 0))  
    {  
        /* Translate virtual-key messages into character messages */  
        TranslateMessage(&messages);  
        /* Send message to WindowProcedure */  
        DispatchMessage(&messages);  
    }  

    /* The program return-value is 0 - The value that PostQuitMessage() gave */  
    return messages.wParam;  
}  


/*  This function is called by the Windows function DispatchMessage()  */  

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)  
{  
    switch (message)                  /* handle the messages */  
    {  
        case WM_DESTROY:  
            PostQuitMessage (0);       /* send a WM_QUIT to the message queue */  
            break;  
        default:                      /* for messages that we don't deal with */  
            return DefWindowProc (hwnd, message, wParam, lParam);  
    }  

    return 0;  
}

然后选择菜单栏Project->Build Options,弹出Project Build Options,选择工程名称。在Linker settings选项卡下添加libDynamicLibrary.a的路径,即添加需要的库。在Search directories选项卡下的Compiler子选项卡下添加dynamic.h所在的目录路径,即写入项目的头文件目录;在Linker子选项卡下添加libDynamicLibrary.a所在的目录路径,即写入库文件目录。最后,点击编译即可。
需要注意的是,以后单独运行编译后的exe执行文件时,需要将dll文件(此处为DynamicLibrary.dll)放在同一目录下,不然运行时可能会崩溃。

参考:
codeblocks 配置编译器 1配置编译器的path, include, lib http://www.verydemo.com/demo_c167_i5481.html
C/C++ 跨平台交叉编译、静态库/动态库编译、MinGW、Cygwin、CodeBlocks使用原理及链接参数选项 http://www.cnblogs.com/LittleHann/p/3980364.html
什么是DLL? http://support2.microsoft.com/kb/815065/zh-cn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值