静态链接库、动态链接库

1.代码的重用 一般在程序中,代码重用可以用函数来实现; 给其它程序重用代码的实现有两种方式:     1】静态链接库     2】动态链接库 也就是可以用来实现模块化;   1.静态链接库 1)创建静态链接库 vc6中创建:File    ->new    ->Projects    ->Win32 Static Library 静态链接库、动态链接库静态链接库、动态链接库   头文件: #if !defined(AFX_HELLO_H__0A93BBBF_3714_47C0_A953_6BC530AAD15A__INCLUDED_) #define AFX_HELLO_H__0A93BBBF_3714_47C0_A953_6BC530AAD15A__INCLUDED_   #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000   int Plus(int x, int y); int Sub(int x, int y); int Mul(int x, int y); int Div(int x, int y);   #endif // !defined(AFX_HELLO_H__0A93BBBF_3714_47C0_A953_6BC530AAD15A__INCLUDED_)   cpp文件: #include "Hello.h" int Plus(int x, int y) {     return x+y; }   int Sub(int x, int y) {     return x-y; }   int Mul(int x, int y) {     return x*y; }   int Div(int x, int y) {     return x/y; }   然后编译,会生成一个.lib文件; 创建完成;   2)使用静态链接库   1】方式一:                                 将xxx.h 和 xxx.lib复制到要使用的项目中                             在需要使用的文件中包含:#include "xxx.h"                             在需要使用的文件中包含:#pragma comment(lib, "xxx.lib")       将编译生成的.dll文件和头文件复制到目标工程根目录; 静态链接库、动态链接库静态链接库、动态链接库 代码: #include "stdafx.h"   //引入静态链接库中的头文件 #include "Hello.h"   //告诉编译器去哪里找lib文件 #pragma comment(lib, "StaticHello.lib")   int main(int argc, char* argv[]) {     int x = 1;     int y = 2;     //使用静态链接库中的方法     printf("相加的值为:%d\n", Plus(1,2));     getchar();     return 0; }   方式二:                         将xxx.h 和 xxx.lib复制到要使用的项目中                     在需要使用的文件中包含:#include "xxx.h"         静态链接库、动态链接库静态链接库、动态链接库            3)静态链接库的缺点 使用静态链接生成的可执行文件体积较大,造成浪费                     我们常用的printf、memcpy、strcpy等就来自这种静态库             用od的“E”可以查看程序包含了哪些模块; 静态链接库实际上是假的模块化; 静态链接库的代码实际上在编译时被编译到exe中了;     2.动态链接库 1)创建 vc6中创建:File    ->new    ->Projects    ->Win32 Dynamic-Link Library         头文件: extern "C" _declspec(dllexport) __stdcall int Plus (int x,int y);           extern "C" _declspec(dllexport) __stdcall int Sub (int x,int y);         extern "C" _declspec(dllexport) __stdcall int Mul (int x,int y);         extern "C" _declspec(dllexport) __stdcall int Div (int x,int y);           源文件: int __stdcall Plus(int x,int y)             {                 return x+y;         }             int __stdcall Sub(int x,int y)             {                 return x-y;         }             int __stdcall Mul(int x,int y)             {                 return x*y;         }             int __stdcall Div(int x,int y)             {                 return x/y;         }                说明:                         1、extern 表示这是个全局函数,可以供各个其他的函数调用;        2、"C" 按照C语言的方式进行编译、链接               因为c不支持重载,而c++支持;如果不按照c导出,编译器可能会因为防止重载而改函数名;                   __declspec(dllexport)告诉编译器此函数为导出函数;      2)使用 1】方式一:隐式连接                             步骤1:将 *.dll  *.lib 放到工程目录下面              动态链接库代码放在.dll中,.lib中放的是去哪里找代码信息;                        步骤2:将 #pragma comment(lib,"DLL名.lib") 添加到调用文件中                             步骤3:加入函数的声明                         extern "C" __declspec(dllimport) __stdcall int Plus (int x,int y);                           extern "C" __declspec(dllimport) __stdcall int Sub (int x,int y);                         extern "C" __declspec(dllimport) __stdcall int Mul (int x,int y);                         extern "C" __declspec(dllimport) __stdcall int Div (int x,int y);                注意函数导入和导出的调用约定要一致;         dll的导入一般使用__stdcall内平栈;   说明:                         __declspec(dllimport)告诉编译器此函数为导入函数;                                              2】方式二:显示链接   显示连接就是编译器不知道什么时候调用dll也不知道dll在哪,而是自己调用;                       步骤1:    //定义函数指针                         typedef int (__stdcall *lpPlus)(int,int);                         typedef int (__stdcall *lpSub)(int,int);                         typedef int (__stdcall *lpMul)(int,int);                         typedef int (__stdcall *lpDiv)(int,int);             步骤2:  //声明函数指针变量                             lpPlus myPlus;                         lpSub mySub;                         lpMul myMul;                         lpDiv myDiv;                       步骤3:  //    //动态加载dll到内存中                         HINSTANCE   hModule = LoadLibrary("DllDemo.dll");         步骤4:  //获取函数地址                             myPlus = (lpPlus)GetProcAddress(hModule,   "_Plus@8");                         mySub = (lpSub)GetProcAddress(hModule,   "_Sub@8");                         myMul = (lpMul)GetProcAddress(hModule,   "_Mul@8");                         myDiv = (lpDiv)GetProcAddress(hModule,   "_Div@8");        因为是 __stdcall,编译器会将函数名改为“_函数名@8”,如果是默认的__cdecl则不会改名;   步骤5:    //调用函数                         int a = myPlus(10,2);                         int b = mySub(10,2);                         int c = myMul(10,2);                         int d = myDiv(10,2);              特别说明:                                                     Handle 是代表系统的内核对象,如文件句柄,线程句柄,进程句柄。                                                     HMODULE 是代表应用程序载入的模块                                                     HINSTANCE 在win32下与HMODULE是相同的东西 Win16 遗留                                                     HWND 是窗口句柄     其实就是一个无符号整型,Windows之所以这样设计有2个目的:                                                 1、可读性更好    ->这几个宏定义都是无符号整型,但用不同的名字可以知道具体是干什么用的,比如看到HWAND就知道这是一个窗口;                                                2、避免在无意中进行运算    ->提醒用户,比如看到HWAND就知道这不是普通的数,不是用来做计算的;                           静态链接库、动态链接库静态链接库、动态链接库   3)总结 dll中的代码在编译后不会整合到exe中; 而是在自己独立的模块中; 比如:发现dll中某个函数有问题时,只需要修改dll就可以了,并不需要exe重新编译; 而静态链接库必须重新生成exe; dll的这一特性可以实现模块化;   3.使用.def导出 很多时候,知道了一个函数名大概就能猜到这个函数是干什么用的; 为了安全,有时需要将重要的函数的名字隐藏,比如验证密码的函数; 使用.def导出dll时,可以让函数名字隐藏; 使用.def导出的项目首先要是一个动态链接库的项目;也就是说这是一种dll导出的方式   *.h文件: int Plus (int x,int y);   int Sub (int x,int y); int Mul (int x,int y); int Div (int x,int y);     *.cpp文件 int Plus(int x,int y) {     return x+y; }   int Sub(int x,int y) {     return x-y; }   int Mul(int x,int y) {     return x*y; }   int Div(int x,int y) {     return x/y; }   *.def文件 EXPORTS   Plus   @12 Sub    @15 NONAME Mul    @13 Div    @16 例如:Plus是函数名,@12就是说函数Plus的导出序号是12,这个序号可以随便写; 加了NOME的函数在导出时会看不见函数名;   使用序号导出的好处:                     名字是一段程序就精华的注释,通过名字可以直接猜测到函数的功能                     通过使用序号,可以达到隐藏的目的.                    
上一篇:乐优商城--服务(六) : 页面微服务


下一篇:中文自然语言处理相关的开放任务,数据集,以及当前最佳结果