看过关于动态库的调用例子,于是决定动手做一做:
dll的对外接口声明头文件,Mydll.h:
//Mydll.h
#include <stdio.h>
#include <stdlib.h>
#include "Public.h"
#define DLL_EXPORT /*extern "c"*/ __declspec(dllexport) //导出
#define CUST_API _stdcall //标准调用
DLL_EXPORT void CUST_API DisplayVersion(TCHAR *Info); //显示版本
DLL_EXPORT int CUST_API Calc(int ia,int ib);
//DLL_EXPORT int CUST_API MetiCalc(int ia,int ib); //新增加接口
//mydll.cpp
#include "MyDll.h"
void CUST_API DisplayVersion(TCHAR *Info)
{
wcscpy_s(Info,sizeof(VERSION),VERSION); //#define VERSION ver 1.0
return;
}
int CUST_API Calc(int ia,int ib)
{
return ia+ib;
}
int CUST_API MetiCalc(int ia,int ib)
{
return ia*ib;
}
编译后,生成DllTest.lib 和 DllTest.dll
第一种方法:静态调用
理解:lib描述dll信息和函数入口地址,在编译时期加载到可执行程序中的。
若dll增加新API接口,新接口在使用时,必须要同时更新lib 才能使用,否则会找不到新接口函数的地址,由此可见,lib包含了描述dll 的接口描述信息。
//dlltest.h
#include <iostream>
#include <Windows.h>
using namespace std;
#pragma comment(lib,"..\\ApDll\\DllTest.lib") //加载lib库
#define DLL_EXPORT /*extern "c"*/ __declspec(dllexport) //导出
#define CUST_API _stdcall //标准调用
DLL_EXPORT void CUST_API DisplayVersion(TCHAR *Info); //dll中显示版本函数
DLL_EXPORT int CUST_API Calc(int ia,int ib);
DLL_EXPORT int CUST_API MetiCalc(int ia,int ib);
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR Version[50] = {0};
int a = 10,b=12;
DisplayVersion(Version);
wcout<<Version<<endl;
wcout<<Calc(a,b)<<endl;
}
Result: ver 1.0
120
第二种方法:动态加载
首先,要定义指向动态库中所对外提供的函数类型,的函数指针。
函数指针定义的理解:
typedef void(_stdcall *FunName)(paramtypes 1,paramtypes 2);//定义指向调用类型为_stdcall,参数个数,类型如paramtypes1,paramtypes 2,返回值为void类型的函数指针
这里注意,定义函数指针时, 返回值 (*pName)(参数),3个部分;
然后,LoadLibrary(Path); Path为dll所在路径,可以是system目录,也可以其他指定目录。加载成功之后会返回一个Hmodel模块句柄。
再利用这个模块句柄去,获取相应函数的地址。
函数指针调用时,不同于普通的指针,它不需要间接寻址,“*”;
用完dll之后要记得ReleaseLibrary() ;
#include <iostream>
#include <Windows.h>
using namespace std;
typedef void (CUST_API *DisVer)(TCHAR *Info);
typedef int (CUST_API *CalcOprt)(int ia,int ib);
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR Version[50] = {0};
int a = 10,b=12;
HMODULE hmodle = LoadLibrary(_T("..\\ApDll\\DllTest.dll")); //动态加载dll
if(NULL == hmodle)
{
wcout<<"load dll failed!"<<endl;
return -1;
}
DisVer displayVer = (DisVer)::GetProcAddress(hmodle,"DisplayVersion"); //根据模块地址,按找函数名,获取函数地址
DisplayVersion(Version);
try
{
if (NULL == displayVer)
{
wcout<<_T("Load function error!")<<endl;
}
(displayVer)(Version); //用函数指针调用函数
wcout<<Version<<endl;
}
catch (...)
{
;
}
system("pause");
return 0;
}
看十,百遍,不如自己敲一遍,小小的动态库调用,也是有讲究的。