1.创建一个动态链接库
l 使用VC6新创建一个“Win32 Dynamic Application”工程,名称为“testdll”,创建类型为“一个空的DLL项目工程”;
l 在菜单“工程”中的“增加到工程”中选择“文件”,为该工程添加一个存在的testdll.cpp文件,testdll.cpp内容如下:
#define DLLEXPORT __declspec( dllexport )
extern "C" DLLEXPORT
void sum(int x,int y,int *z)
{
*z = x+y;
}
extern "C" DLLEXPORT
int prod(int x,int y)
{
return x*y;
}
按“F7”编译该工程,在debug 目录下会得到一个静态库“testdll.lib”和一个动态库“testdll.dll”文件;
2.使用动态库
隐式链接使用动态库:
在任意一个目录新建内一个名为“testapp.cpp”文件,内容如下:
#include <stdio.h>
#pragma comment(lib," testdll.lib")
void sum(int x,int y,int *z);
int prod(int x,int y);
void main()
{
int z=0;
sum(8,7,&z);
printf("sum=%d/n",z);
printf("prod=%d",prod(3,4));
}
该文件保存好后使用一个新的VC6打开,然后按“F7”编译,系统会提示为该文件创建一个工程,按“确定”会得到“testapp”工程;
将刚刚创建的“testdll.lib”和“testdll.dll”两个文件放置新生成“testapp”的目录下,在VC环境里按“Ctrl+F 5 ” 会看到运行的结果;
显示链接使用动态库:
显示链接在编译时不需要链接lib库文件,也无需为该库的头文件。
按上述创建隐式链接的方法新创建一个空的文件“testapp2.cpp”,内容如下:
#include <windows.h>
#include <stdio.h>
typedef void (*SUM_PROC)(int,int,int *);
typedef int (*PROD_PROC)(int,int);
void main()
{
HMODULE hm=LoadLibrary("testdll.dll");
SUM_PROC sum = (SUM_PROC)GetProcAddress(hm,"sum");;
int z=0;
sum(56,9,&z);
PROD_PROC prod=(PROD_PROC)GetProcAddress(hm,"prod");
prod(4,8);
FreeLibrary( hm );
}
只将“testdll.dll”拷贝至该应用程序的目录下,编译并运行可看到结果。
3.注意事项:
l 无论是库文件,还是应用程序文件,文件的扩展名很重要,一般选择.cpp,这会按C++规则编译并链接生成,若使用.c扩展名则按C规则编译生成;
l 库文件的函数的前面加的extern "C"是必须的,它的功能是:该库不仅仅可为C++应用程序所使用,也可以为C应用程序使用;
l 生成库或应用程序的函数调用规则(在“工程”->“设置”的“C++”页面,分类选“Code Generation”后看到的“Calling convention”),按默认的“ __cdecl *” 设置;
l 如果在应用程序的debug版本调用动态库出现__chkesp错,原因是应用程序在调用库函数前检查得到ESP指针和函数调用后的不一致而报错,仅编译debug版本可以将/GZ选项去掉即可;
l 动态库生成还可以使用def描述输出库函数文件方式获得,如上述的def文件描述为:
LIBRARY TESTDLL
EXETYPE WINDOWS
CODE PRELOAD MOVEABLE DISCARDABLE
DATA PRELOAD MOVEABLE SINGLE
EXPORTS
sum @1
prod @2
将该文件一同加入到库的工程中,并去掉导出关键字__declspec( dllexport )
l 应用程序为C规则的调用方式还有一种,如下程序:
void main()
{
HMODULE hm=LoadLibrary("user32.dll");
FARPROC fun;
fun=GetProcAddress(hm,"MessageBoxA");
fun(NULL,"hello","hello",MB_OK);
}
上述程序是可通过编译并正确执行的,根据试验,__declspec( dllexport )是不能得到的,而是将库函数前加extern int far pascal ,并添加导出描述文件def生成的;
l 动态库文件可用VC++的工具:Depends 查看该库的函数描述,若发现函数名不是你源文件中的函数名,例如添加了一些?@之类,说明该库在编译规则上不合适,需调整,重点检查该库的文件扩展名、有无extern “C”、及函数的调用规则。