一 Windows的库
由于项目的复杂程度,或者为了提高代码的
重用率等等,所以才引入了库程序。
库包含两种:
1 静态库:扩展名为LIB的文件,是不能被
加载的程序,可以理解为目标程序的
归档。
2 动态库:扩展名是DLL的文件,是可以被
应用程序加载的程序。
二 静态库
1 静态库的特点
1.1 目标程序的归档
1.2 静态库的代码会被嵌入到程序当中。
1.3 程序执行时不需要静态库存在
2 C语言静态库
2.1 创建静态库
创建Win32静态库项目,使用*.C文件建立
项目。
2.2 添加静态库函数
2.3 在程序中将静态库导入
2.3.1 项目的Setting里设置
2.3.2 使用关键字 pragma
#pragma comment(lib, "../lib/winclib.lib")
2.4 使用静态库提供的函数
在C语言程序中,直接使用函数即可。
3 C++语言的静态库
3.1 创建静态库
创建Win32静态库项目,使用*.CPP文件建立
项目。
3.2 添加静态库的函数
3.3 导入静态库
3.3.1 项目的Setting里设置
3.3.2 使用关键字 pragma
#pragma comment(lib, "../lib/wincpplib.lib")
3.4 定义库函数的原形
int CPP_Add( int nAdd1, int nAdd2 );
3.5 使用库函数
3.6 注意:
如果在CPP文件使用C语言静态库,定义的
静态库函数原形,需要增加 extern "C".
例如:
extern "C" int C_Add( int nAdd1, int nAdd2 );
Windows DLL中变量和类的使用方法类似:
一、变量的使用
建立(empty)DLL动态库 Dll_Value:
右键工程-设置-常规-输出文件-“../lib”:(输出文件为:Dll_Value.lib)
右键工程-设置-常规-链接(Link)-“../bin/Dll_Value.dll”
1.定义变量:
新建cpp文件
//导出方式①
__declspec(dllexport) int g_nValue = 100;
//导出方式②DEf
int g_nValue2 = 200;
//导出方式②:写入DEf文件
新建文本文件dll_value.def
LIBRARY Dll_Value
EXPORTS
g_nValue2 @1 DATA
2.导入lib文件
#pragama comment(lib, "../lib/Dll_Value.lib")
3.定义变量、.使用
#include "StdAfx.h"
#pragma comment(lib, "../lib/Dll02.lib")
extern __declspec(dllimport) int g_nValue;
extern __declspec(dllimport) int g_nValue2;
int main()
{
printf("Value:%d\n",g_nValue);
printf("Value2:%d\n",g_nValue2);
return 0;
}
二、类的使用
建立(empty)DLL动态库 Dll_Class:
右键工程-设置-常规-输出文件-“../lib”:(输出文件为:Dll_Class.lib)
右键工程-设置-常规-链接(Link)-“../bin/Dll_Class.dll”
1.定义变量:
新建头文件CMath
#ifndef _CMATH_H_
#define _CMATH_H_
class __declspec(dllexport) CMath
{
public:
int Add(int nAdd1, int nAdd2);
int Sub(int nSub1, int nSub2);
};
#endif //_CMATH_H_
新建cpp文件:
#include "CMath.h"
int CMath::Add(int nAdd1, int nAdd2)
{
return nAdd1 + nAdd2;
}
int CMath::Sub(int nSub1, int nSub2)
{
return nSub1 - nSub2;
}
2.导入lib文件
#pragama comment(lib, "../lib/Dll_Class.lib")
3.定义类、使用
#include "StdAfx.h"
#pragma comment(lib, "../lib/Dll02.lib")
class __declspec(dllimport) CMath
{
public:
int Add(int nAdd1, int nAdd2);
int Sub(int nSub1, int nSub2);
};
int main()
{
CMath m;
printf("Value:%d\n",m.Add(11,11));
printf("Value2:%d\n",m.Sub(9,99));
return 0;
}
/************/常用DLL类导出方式:
#ifndef _CMATH_H_
#define _CMATH_H_
#define _DLL_CLASS_
#ifdef _DLL_CLASS_
#define _DLL_CLASS_EXT_ __declspec(dllexport)
#else
#define _DLL_CLASS_EXT_ __declspec(dllimport)
#endif _DLL_CLASS_
#endif //_CMATH_H_
使用时直接包含头文件即可如下:
#include "StdAfx.h"
#pragma comment(lib, "../lib/Dll02.lib")
extern __declspec(dllimport) int g_nValue;
extern __declspec(dllimport) int g_nValue2;
#include "../Dll02/math.h"
/*
class __declspec(dllimport) CMath
{
public:
int Add(int nAdd1, int nAdd2);
int Sub(int nSub1, int nSub2);
};
*/
int main()
{
CMath m;
printf("Value:%d\n",m.Add(11,11));
printf("Value2:%d\n",m.Sub(9,99));
return 0;
}
/*****************************************************************/
DLL中调用函数分为隐式调用和显式调用:
DLL源文件CPP:
__declspec(dllexport) int DLL_Add(int nAdd1, int nAdd2) //C++方式编译
{
return nAdd1 + nAdd2;
}
extern "C" __declspec(dllexport) int DLL_Sub(int nSub1, int nSub2)//C方式编译
{
return nSub1 - nSub2;
}
int DLL_Mul(int nMul1, int nMul2)//配合def文件
{
return nMul1 * nMul2;
}
导入def文件
LIBRARY Dll_Func
EXPORTS
DLL_Mul @1
编译生成DLL,lib时 设置-常规-输出文件-“../lib” 设置-连接-输出文件名-“../bin/DLLXX.dll”
1、隐式调用
#include <stdio.h>
//隐式链接加载DLL,设置-连接-输出文件名-“../bin/UseDll_Func.exe”
#pragma comment(lib, "../lib/Dll_Func.lib")
int DLL_Add(int nAdd1, int nAdd2);
extern "C" int DLL_Sub(int nSub1, int nSub2);
int DLL_Mul(int nMul1, int nMul2);
int main()
{
int nAdd = DLL_Add(100,100);
printf("nAdd:%d \n",nAdd);
int nSub = DLL_Sub(100,100);
printf("nSub:%d \n",nSub);
int nMul = DLL_Mul(100,100);
printf("nMul:%d \n",nMul);
return 0;
}
2.显式调用
#include <windows.h>
#include <stdio.h>
//测试显式连接调用DLLFunc
typedef int (*DLL_ADD)(int a, int b);
typedef int (*DLL_SUB)(int a, int b);
typedef int (*DLL_MUL)(int a, int b);
void UseFunc()
{
HMODULE hDll = (HMODULE)LoadLibrary("Dll_Func.dll");
if (NULL == hDll)
{
perror("LoadDll err \n");
return;
}
printf("%p \n", hDll);
DLL_ADD DLL_Add = (DLL_ADD)GetProcAddress(hDll, "DLL_Add");//此函数用__declspec(dllexport) C++编译器编译后函数名不在是DLL_Add所以找不到该函数
if (NULL == DLL_Add )
{
perror("Load Add err \n");
}
DLL_SUB DLL_Sub = (DLL_SUB)GetProcAddress(hDll, "DLL_Sub");
if (NULL == DLL_Sub)
{
perror("Load Add err \n");
}
else
{
int nSub = DLL_Sub(100,90);
printf("nSub:%d \n",nSub);
}
DLL_MUL DLL_Mul = (DLL_MUL)GetProcAddress(hDll, "DLL_Mul");
if (NULL == DLL_Mul)
{
perror("Load Add err \n");
}
else
{
int nMul = DLL_Mul(10,90);
printf("%d \n",nMul);
}
FreeLibrary(hDll);
}
int main()
{
UseFunc();
return 0;
}