做项目的时候,很多情况下都需要用到客户所提供的库,因为每个公司代码里识别的函数参数不相同,导致客户提供的库不能直接使用,需要再封装一层进行转化。
VC++调用外部函数其实非常的方便,因为VC++本身就可以新建一个dll项目,同时也提供获取库的函数,使用向导来新建,十分快捷。
步骤
1、使用VC++创建一个新的win32项目,然后向导里面选择dll工程。这里可以不使用空目录,让VC++自动建立一个dllmain.cpp文件。
2、在工程目录文件下(即自己工程的.cpp文件),添加外部API的接口函数,这里有两种方法,可以使用extern “C” 的方式,也可以自己新建一个.def模块定义文件来声明,两种方法各有各的好处,具体可参考:
两种动态链接库的使用比较
.def动态库文件的使用
这里我使用的是extern "C"的方法
#ifndef KEY_API
#define KEY_API extern "C" __declspec(dllexport)
#endif
//这是我们自己处理的函数
KEY_API void demmo(unsigned char *seed, unsigned char *key);
3、条件部署完后,需要先创建一个用于转换的函数类型,并且创建函数指针,函数指针的所指向的参数要和外部引用的函数参数一致。这里要根据具体实际情况来定义。
enum VKeyGenResultExOpt
{
KGREO_Ok = 0,
KGREO_BufferToSmall = 1,
KGREO_SecurityLevelInvalid = 2,
KGREO_VariantInvalid = 3,
KGREO_UnspecifiedError = 4
};
typedef VKeyGenResultExOpt (*pGenerateKeyExOpt)(
const unsigned char* ipSeedArray,
unsigned short iSeedArraySize,
const unsigned int iSecurityLevel,
const char* iVariant,
unsigned char* ioKeyArray,
unsigned int iKeyArraySize,
unsigned int& oSize
);
4、加载依赖库
使用LoadLibrary()函数来加载依赖库,如果已经知道依赖库的路径,那么直接使用该函数即可,但如果路径不大确定,只能确定依赖库和我们绑定库在同一目录下,则需要其他办法。
HMODULE hMod = GetModuleHandle(_T("ycrcu.dll"));
//先获取当前库的路径,并截取到上一层目录
GetModuleFileName(hMod, szDLLPath, MAX_PATH);
_tcsrchr(szDLLPath, _T('\\'))[1] = 0;
//将路径与依赖库名绑定即可
TCHAR newPath[MAX_PATH] = {0};
wsprintf(newPath, _T("%sGenerateKeyExImpl.dll"), szDLLPath);
HINSTANCE h_dll = LoadLibrary(newPath);
5、当依赖库加载完成后,将函数指针指向依赖库中的函数即可调用依赖库的函数,同时将外部调用传给我们库的参数,按函数所需的参数要求传给依赖库中的函数即可调用完成。
pGenerateKeyExOpt GenerateKeyExOpt = NULL;
if (NULL != h_dll)
{
GenerateKeyExOpt = (pGenerateKeyExOpt)GetProcAddress(h_dll, "GenerateKeyEx");
if (NULL != GenerateKeyExOpt)
{
GenerateKeyExOpt(seed, 4, iSecurityLevel, NULL, key, 64, oActualKeyArraySize);
}
}
6、库中的运行流程
外部调用我们的库时,首先会执行dllmain.cpp的程序,执行完后,才会执行我们自己建立的demo.cpp程序,并且由于声明了外部接口函数,最后根据我们的调用,找到依赖库里面的函数运行,最后返回至我们自己的库程序中结束。
总结
这里最主要的是使用了这几个系统函数:
1、GetModuleHandle()
2、GetModuleFileName()
3、LoadLibrary()
4、GetProcAddress()
其实只要知道了具体的思路以及所需要的函数,调用外部库的函数其实是非常简单的。