静态库 动态库 的封装以及使用 (个人笔记)
静态库
静态库建立
新建工程 static lib
编译
保留 lib文件和.h文件
使用:
#include "..//test.h" //包含库的头文件
#pragma comment(lib,"..//debug//staticlibtest.lib") //引用库的lib文件
dll库封装
函数使用_declspec(dllexport) 声明函数将用于导出
例如
_declspec(dllexport) int add(int , int )
使用extern "C" 可是使函数名不重写。当然 也不可以使用重载了。(使用extern "C" 就是说函数是C语言的程序,当然没有重载了。)
_declspec(dllimport) 表明函数是从动态链接库引入的。(虽然extern 也可以用,但是它比extern可能会促进优化)
导出class
class _declspec(dllexport) point{/* 省略类的实现*/ };
如果加在类方法的名称前 那么仅导出该方法
vc的标准调用使用pascal调用约定,它不同于_stdcall
extern "C" int add(int ,int) -> add
_stdcallint add(int ,int) -> _add@8 (参数有8个字节)
int add(int ,int) -> ?add@@YAHHH@Z
.h文件
#ifdef DLL_API
#else
#define DLL_API _declspec(dllimport)
#endif
DLL_API int add(int ,int);
DLL_API float add(float a,float b);
#undef DLL_API
.c文件
#define DLL_API _declspec(dllexport)
#include "dll.h"
#undef DLL_API
int add(int a,int b)
{
return a+b;
}
float add(float a,float b)
{
return a+b;
}
用.def文件创建工程MyDll。
.def文件为链接器提供了有关被链接程序的导出、属性及其他方面的信息。
使用.def文件创建DLL,就不需要再在上个例子创建的工程中的MyDll.h文件中包括extern "C" _declspec(dllexport)声明部分了。
在该工程中加入一个文本文件,命名为MyDll.def,
在该文件中加入如下代码:
LIBRARY MyDll
EXPORTS
Add @1
如果导出名和源文件函数名不同
可使用如下方法导出
entryname = internalname
entryname为导出名 internalname为源文件中的函数名(详见exports msdn)
其中LIBRARY语句说明该def文件是属于相应DLL的,EXPORTS语句下列出要导出的函数名称。
我们可以在.def文件中的导出函数后加@n,如Add@1,表示要导出的函数顺序号,在进行显式连时可以用到它。
DLL编译成功后,打开工程中的Debug目录,同样也会看到MyDll.dll和MyDll.lib文件。
dll使用
隐式链接
#include "XXXX" //引入头文件
#pragma comment(lib,"xxx.lib") //使得编译器可以找到头文件中的函数信息
然后 就可以向普通函数使用了
动态加载
HINSTANC hInst = LoadLibrary("libname.dll"); //引入DLL
ADDPROC fun = (ADDPROC)GetProcAddress(hInst, "funName"); //通过函数名称导出函数
ADDPROC fun = (ADDPROC)GetProcAddress(hInst, MAKEINTRESOURCE(1));//通过函数索引导出函数
BOOL FreeLibrary(hInst);// 不使用DLL了 记得释放DLL
最后
DllMain是dll被载入时调用的函数。目前没有发现他有什么用,不用定义好像也没有什么影响。因此暂时不予考虑。