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

静态库和动态库的区别

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

[cpp] view
plain
copy

  1. #ifndef STATIC_H_INCLUDED
  2. #define STATIC_H_INCLUDED
  3. #ifdef __cplusplus
  4. extern "C"
  5. {
  6. #endif
  7. int SampleAddInt(int i1, int i2);
  8. void SampleFunction1();
  9. int SampleFunction2();
  10. #ifdef __cplusplus
  11. }
  12. #endif
  13. #endif // STATIC_H_INCLUDED

static.cpp

[cpp] view
plain
copy

  1. #include "static.h"
  2. // A function adding two integers and returning the result
  3. int SampleAddInt(int i1, int i2)
  4. {
  5. return i1 + i2;
  6. }
  7. // A function doing nothing ;)
  8. void SampleFunction1()
  9. {
  10. // insert code here
  11. }
  12. // A function always returning zero
  13. int SampleFunction2()
  14. {
  15. // insert code here
  16. return 0;
  17. }

2.建立主工程

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

main.cpp

[cpp] view
plain
copy

  1. #include <iostream>
  2. #include "static.h"
  3. using namespace std;
  4. int main()
  5. {
  6. int a=1,b=2;
  7. cout << "a + b = "<<SampleAddInt(a,b)<< endl;
  8. return 0;
  9. }

然后选择菜单栏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

[cpp] view
plain
copy

  1. #ifndef __DYNAMIC_H__
  2. #define __DYNAMIC_H__
  3. #include <windows.h>
  4. /*  To use this exported function of dll, include this header
  5. *  in your project.
  6. */
  7. #ifdef BUILD_DLL
  8. #define DLL_EXPORT __declspec(dllexport)
  9. #else
  10. #define DLL_EXPORT __declspec(dllimport)
  11. #endif
  12. #ifdef __cplusplus
  13. extern "C"
  14. {
  15. #endif
  16. void DLL_EXPORT SomeFunction(const LPCSTR sometext);
  17. #ifdef __cplusplus
  18. }
  19. #endif
  20. #endif // __DYNAMIC__

dynamic.cpp

[cpp] view
plain
copy

  1. #include "dynamic.h"
  2. // a sample exported function
  3. void DLL_EXPORT SomeFunction(const LPCSTR sometext)
  4. {
  5. MessageBoxA(0, sometext, "DLL Message", MB_OK | MB_ICONINFORMATION);
  6. }
  7. extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
  8. {
  9. switch (fdwReason)
  10. {
  11. case DLL_PROCESS_ATTACH:
  12. // attach to process
  13. // return FALSE to fail DLL load
  14. break;
  15. case DLL_PROCESS_DETACH:
  16. // detach from process
  17. break;
  18. case DLL_THREAD_ATTACH:
  19. // attach to thread
  20. break;
  21. case DLL_THREAD_DETACH:
  22. // detach from thread
  23. break;
  24. }
  25. return TRUE; // succesful
  26. }

2.建立主工程

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

main.cpp

[cpp] view
plain
copy

  1. #include <windows.h>
  2. #include "dynamic.h"
  3. /*  Declare Windows procedure  */
  4. LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
  5. /*  Make the class name into a global variable  */
  6. char szClassName[ ] = "CodeBlocksWindowsApp";
  7. int WINAPI WinMain (HINSTANCE hThisInstance,
  8. HINSTANCE hPrevInstance,
  9. LPSTR lpszArgument,
  10. int nCmdShow)
  11. {
  12. HWND hwnd;               /* This is the handle for our window */
  13. MSG messages;            /* Here messages to the application are saved */
  14. WNDCLASSEX wincl;        /* Data structure for the windowclass */
  15. /* The Window structure */
  16. wincl.hInstance = hThisInstance;
  17. wincl.lpszClassName = szClassName;
  18. wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
  19. wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
  20. wincl.cbSize = sizeof (WNDCLASSEX);
  21. /* Use default icon and mouse-pointer */
  22. wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
  23. wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
  24. wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
  25. wincl.lpszMenuName = NULL;                 /* No menu */
  26. wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
  27. wincl.cbWndExtra = 0;                      /* structure or the window instance */
  28. /* Use Windows‘s default colour as the background of the window */
  29. wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
  30. /* Register the window class, and if it fails quit the program */
  31. if (!RegisterClassEx (&wincl))
  32. return 0;
  33. /* The class is registered, let‘s create the program*/
  34. hwnd = CreateWindowEx (
  35. 0,                   /* Extended possibilites for variation */
  36. szClassName,         /* Classname */
  37. "Code::Blocks Template Windows App",       /* Title Text */
  38. WS_OVERLAPPEDWINDOW, /* default window */
  39. CW_USEDEFAULT,       /* Windows decides the position */
  40. CW_USEDEFAULT,       /* where the window ends up on the screen */
  41. 544,                 /* The programs width */
  42. 375,                 /* and height in pixels */
  43. HWND_DESKTOP,        /* The window is a child-window to desktop */
  44. NULL,                /* No menu */
  45. hThisInstance,       /* Program Instance handler */
  46. NULL                 /* No Window Creation data */
  47. );
  48. /* Make the window visible on the screen */
  49. ShowWindow (hwnd, nCmdShow);
  50. SomeFunction("Dynamic Tester");
  51. /* Run the message loop. It will run until GetMessage() returns 0 */
  52. while (GetMessage (&messages, NULL, 0, 0))
  53. {
  54. /* Translate virtual-key messages into character messages */
  55. TranslateMessage(&messages);
  56. /* Send message to WindowProcedure */
  57. DispatchMessage(&messages);
  58. }
  59. /* The program return-value is 0 - The value that PostQuitMessage() gave */
  60. return messages.wParam;
  61. }
  62. /*  This function is called by the Windows function DispatchMessage()  */
  63. LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  64. {
  65. switch (message)                  /* handle the messages */
  66. {
  67. case WM_DESTROY:
  68. PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
  69. break;
  70. default:                      /* for messages that we don‘t deal with */
  71. return DefWindowProc (hwnd, message, wParam, lParam);
  72. }
  73. return 0;
  74. }

然后选择菜单栏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

时间: 2024-08-10 23:19:44

CodeBlocks静态链接与动态链接设置的相关文章

linux 静态链接和动态链接

链接 一个可执行目标文件的生成需要经过预编译(g++ -E).编译(g++ -S).汇编(g++ -c).链接四个步骤.链接是将多个可重定位目标文件合并到一个目标文件的过程.链接由链接器完成,链接器重要完成两个任务: 1.符号(符号表由汇编器构造)解析.也就是将符号引用和符号定义关联起来.其中符号定义和符号引用可能不在同一个目标文件中.而且链接器对多重定义的全局符号的解析有一定的规则:不允许有多个同名强符号(函数和初始化了的全局变量).如果有一个强符号和多个弱符号同名选择强符号.如果有多个弱符号

静态链接与动态链接的区别(转载)

1.转载:http://www.cnblogs.com/kex1n/archive/2011/09/06/2168435.html 动态链接库.静态库.import库区别 动态链接库(Dynamic Linked Library):Windows为应用程序提供了丰富的函数调用,这些函数调用都包含在动态链接库中.其中有3个最重要的DLL,Kernel32.dll,它包含用于管理内存.进程和线程的各个函数: User32.dll,它包含用于执行用户界面任务(如窗口的创建和消息的传送)的各个函数:GD

C的日记-静态链接和动态链接

[静态链接和动态链接]    静态链接:源程序编译之后,如果想要执行,先对目标文件进行链接,链接完成后如果执行了,就把链接好的都装载进内存    缺点:        <1>如果一个目标文件被重复使用,每次都会把目标文件载入内存,造成浪费:        <2>如果相对某个目标文件进行更新,需要先把这个目标文件重新编译+链接,然后重新载入内存.    动态链接:在程序开始运行后(装载到内存)才开始把目标文件依次加载到内存然后编译成可执行文件    优点:        <1&

静态链接和动态链接

1.实例代码 //add.c#include"tmath.h" int tadd(int x,int y) { return x+y; } int tsub(int x,int y) { return x-y; } //mul.c #include"tmath.h" int tmul(int x, int y) { return x*y; } int tdiv(int x,int y) { return x/y; } //main.c #include<std

程序的静态链接,动态链接和装载

一.程序编译链接的整体流程 通常我们使用gcc来生成可执行程序,命令为:gcc hello.c,默认生成可执行文件a.out 其实编译(包括链接)的命令:gcc hello.c 可分解为如下4个大的步骤: 预处理(Preprocessing) 编译(Compilation) 汇编(Assembly) 链接(Linking) gcc compilation 1.       预处理(Preproceessing) 预处理的过程主要处理包括以下过程: 将所有的#define删除,并且展开所有的宏定义

学习总结:静态链接和动态链接

链接可分为静态链接和动态链接 静态链接:对函数库的链接是放在编译时期完成的是静态链接 生成静态链接库的步骤: (1)先将源文件编译成 .o 文件: (源文件可从上一篇查看) g++ -c printA.cpp g++ -c printB.cpp 生成的文件为 printA.o printB.o ,-c 的编译选项,表示只执行到编译,输出目标文件. 无论是静态库文件还是动态库文件,都是由 .o 文件创建的 (2)由 .o 文件创建静态库(.a 文件),执行命令: ar cr libmyprint.

静态和动态链接

引言即使是最简单的HelloWorld的程序,它也要依赖于别人已经写好的成熟的软件库,这就是引出了一个问题,我们写的代码怎么和别人写的库集成在一起,也就是链接所要解决的问题. 首先看HelloWorld这个例子:[cpp] view plain copy  1. // main.c    2.   1 #include <stdio.h>    3.   2    4.   3 int main(int argc, char** argv)    5.   4 {    6.   5     

[CSAPP-II] 链接[符号解析和重定位] 静态链接 动态链接 动态链接接口

1 平台 1.1 硬件 Table 1. 硬件(lscpu) Architecture: i686(Intel 80386) Byte Order: Little Endian 1.2 操作系统 Table 2. 操作系统类型 操作系统(cat /proc/version) 位数(uname -a) Linux version 3.2.0-4-686-pae i686(32bit) 1.3 编译器 Table 3. 编译器信息 编译器(gcc -v) gcc (Debian 4.7.2-5) 4

装载与动态链接

装载与动态链接 1可执行文件的装载与进程 可执行文件只有装载到内存后才能被CPU执行.早期的程序装载十分简陋,装载的基本过程就是把程序从外部存储器中读取到内存中的某个位置. 历史有过的装载方式包括覆盖装载.页映射. 1.1 进程虚拟地址空间 程序是一个静态的概念,它就是一些预先编译好的指令和数据集合的一个文件:进程则是一个动态的概念,它是程序运行的一个过程. 每个程序被运行起来以后,都有自己的虚拟地址空间,这个虚拟地址空间的大小由计算机的硬件平台决定,具体地说是由CPU的位数决定的. 1.2 装