静态编译:
优点:
实现代码的重复使用 方便
缺点:
将二进制代码直接编译到exe中 反汇编无法识别
使用静态链接生成的可执行文件体积较大,造成浪费
我们常用的printf、memcpy、strcpy等就来自这种静态库
静态链接库的代码在lib中 而动态链接库的代码在dll里面
创建静态链接库:
1、在VC6中创建项目:Win32 Static Library
2、在项目中创建两个文件:xxx.h 和 xxx.cpp
xxx.h文件:
#if !defined(AFX_TEST_H__DB32E837_3E66_4BE7_B873_C079BC621AF0__INCLUDED_) #define AFX_TEST_H__DB32E837_3E66_4BE7_B873_C079BC621AF0__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
xxx.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; }
3、编译
二、使用静态链接库:
方式一:
将xxx.h 和 xxx.lib复制到要使用的项目中
在需要使用的文件中包含:#include "xxx.h"
在需要使用的文件中包含:#pragma comment(lib, "xxx.lib")
方式二:
将xxx.h 和 xxx.lib复制到要使用的项目中
在需要使用的文件中包含:#include "xxx.h"
一、创建DLL
1、源文件中:
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; }
2、头文件中
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);
说明:
1、extern 表示这是个全局函数,可以供各个其他的函数调用;
2、"C" 按照C语言的方式进行编译、链接
__declspec(dllexport)告诉编译器此函数为导出函数;
二、使用DLL
方式一:隐式连接
步骤1:将 *.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);
说明:
__declspec(dllimport)告诉编译器此函数为导入函数;
方式二:显示链接
步骤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");
步骤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、可读性更好
2、避免在无意中进行运算
联合体:
1、*.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);
2、*.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; }
3、*.def文件
EXPORTS Plus @12 Sub @15 NONAME Mul @13 Div @16
4、使用序号导出的好处:
名字是一段程序就精华的注释,通过名字可以直接猜测到函数的功能
通过使用序号,可以达到隐藏的目的.