vs2005 创建动态库及其调用方法
又用到dll这个东东了,之前学的一知半解,参考了众多资料终于知道了一点皮毛,赶紧记下,以后都别忘了!
先介绍一下dll创建的方法,我目前知道的在vs2005 c++环境下有两种(不知道意外情况下是否存在第三种),
(1)利用 __declspec(export)
为了编写方面先预定义一下
#ifndef DLLTEST2_EXPORTS
#define DLLTEST2_EXPORTS
#endif#ifdef DLLTEST2_EXPORTS
#define DLLTEST2_API __declspec(dllexport)
#else
#define DLLTEST2_API __declspec(dllimport)
#endif
然后在头文件中声明库函数,格式如下
DLLTEST2_API int MaxFun(int x,int y);
DLLTEST2_API int AddFun(int x,int y);
DLLTEST2_API void PrintFun(void);
嘻嘻,又是这三个函数,浅显易懂啊! 另外说明一下,类似以下的内容自动生成的代码是给你做例子看的,直接注释掉,咱自己写就行

// 此类是从 dlltest2.dll 导出的
//class DLLTEST2_API Cdlltest2 {
//public:
// Cdlltest2(void);
// // TODO: 在此添加您的方法。
//};//extern DLLTEST2_API int ndlltest2;//DLLTEST2_API int fndlltest2(void);
//
然后编辑源文件,对声明的库函数进行定义
#include "stdafx.h"
#include "dlltest2.h"
#include <iostream>#ifdef _MANAGED
#pragma managed(push, off)
#endifBOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:case DLL_THREAD_ATTACH:case DLL_THREAD_DETACH:case DLL_PROCESS_DETACH:break;}return TRUE;
}#ifdef _MANAGED
#pragma managed(pop)
#endif这是导出变量的一个示例
//DLLTEST2_API int ndlltest2=0;
//这是导出函数的一个示例。
//DLLTEST2_API int fndlltest2(void)
//{
// return 42;
//}// 这是已导出类的构造函数。
// 有关类定义的信息,请参阅 dlltest2.h
//Cdlltest2::Cdlltest2()
//{
// return;
//}DLLTEST2_API int MaxFun(int x,int y)
{return ((x>y)?(x):(y));}
DLLTEST2_API int AddFun(int x,int y)
{return (x+y);
}
DLLTEST2_API void PrintFun(void)
{std::cout<<"调用动态库函数"<<std::endl;
}
点击编译就生成了我们想要的dll库了,看这里
下面说第二种方法:
(2)利用def文件
声明函数、定义函数按照我们通常的做法写就可,如下所示:
int MaxFun(int x,int y);int AddFun(int x,int y);void PrintFun(void);
int MaxFun(int x,int y)
{return ((x>y)?(x):(y));}int AddFun(int x,int y)
{return (x+y);
}void PrintFun(void)
{std::cout<<"调用动态库函数"<<std::endl;
}
创建编写def文件,
LIBRARY "dlltest2"
EXPORTS
AddFun @1
MaxFun @2
PrintFun @3
;
dlltest2为动态库的库名,AddFun、MaxFun及PrintFun为导出的函数名,这个一看大家就知道怎么写了,需要说明的是,函数名和@之间的空格不能少,少了可就错了哦,我开始就犯了这样的错误,最后的分号,你当然也不能忽略。同样编译,我们的dll也出来了。
创建过程就完了,有的说第一种方法导出时函数名会被改变,如果编译器不同导入时经常会出错,不知道真假,那我就建议大家用第二种方法咯
下面我也唠叨下使用方法:
1)隐式链接
把我们之前生成的dll、lib和头文件放到要调用的项目目录下,在我们调用的头文件前加上#pragma comment(lib,"dlltest2.lib"),就可以把那些库函数当项目中的函数一样自如调用了,有一个困惑也要注释一下,既然在dll项目中,dll和lib文件是在debug文件下,那我把dll和lib也放到调用项目的dubug文件夹下,应该没问题吧,头文件我放到与debug并行的dlltest2文件夹下,不知道问什么,找不到lib文件,看清楚哦,是debug不是Debug哦,后来我把lib文件与头文件放到一起,就ok了,不知道是和我的路径设置有问题,还是别的原因,暂时也记下了。
2)显示调用
这个说来就麻烦点,要利用LoadLibrary先加载动态库,再利用GetProcAdddress获取各函数的地址,使用完之后再用FreeLibrary释放,哎,不知道有没有说清楚,上代码吧
#include "dlltest2.h"
#include <iostream>
#include <windows.h>
typedef int (*pAddFunc)(int,int);
typedef int (*pMaxFunc)(int ,int);
typedef void (*pPrintFun)(void);int main(void)
{pAddFunc _AddFunc;pMaxFunc _MaxFunc;pPrintFun _PrintFun;HINSTANCE hInstance=LoadLibraryA("dlltest2.dll");if(hInstance==NULL){FreeLibrary(hInstance);}_AddFunc=(pAddFunc)GetProcAddress(hInstance,"AddFun");_MaxFunc=(pMaxFunc)GetProcAddress(hInstance,"MaxFun");_PrintFun=(pPrintFun)GetProcAddress(hInstance,"PrintFun");if(_AddFunc==NULL||_MaxFunc==NULL||_PrintFun==NULL){FreeLibrary(hInstance);//释放空间}_PrintFun();std::cout<<"输入20 25"<<std::endl;std::cout<<"AddFun"<<_AddFunc(20,25)<<std::endl;std::cout<<"MaxFun"<<_MaxFunc(20,25)<<std::endl;FreeLibrary(hInstance);return 0;}
就知道这么多了,先到这里
