动态链接库有3种:NON-MFC DLL,REGRULAR DLL ,EXTENSION DLL
DLL入口:DllMain函数
Windows在加载DLL的时候,需要一个入口函数,就如同控制台或DOS程序需要main函数、WIN32程序需要WinMain函数一样。在前面的例子中,DLL并没有提供DllMain函数,应用工程也能成功引用DLL,这是因为Windows在找不到DllMain的时候,系统会从其它运行库中引入一个不做任何操作的缺省DllMain函数版本,并不意味着DLL可以放弃DllMain函数。
根据编写规范,Windows必须查找并执行DLL里的DllMain函数作为加载DLL的依据,它使得DLL得以保留在内存里。这个函数并不属于导出函数,而是DLL的内部函数。这意味着不能直接在应用工程中引用DllMain函数,DllMain是自动被调用的。
BOOL APIENTRY DllMain(HANDLE hMoudle, DWORD action, LPVOID lpReserved )
{
switch(action)
{
case DLL_PROCESS_ATTACH:
printf("dll_process_attach\n");
break;
case DLL_PROCESS_DETACH:
printf("dll_process_detach\n");
break;
case DLL_THREAD_ATTACH:
printf("dll_thread_attach\n");
break;
case DLL_THREAD_DETACH:
printf("dll_thread_detach\n");
break;
}
return true;
}
如果在DLL中加入想要输出的函数、变量、C++类或其它函数,可以调用VC的关键字_declspec(dllexport)。
动态链接库的调用可以分为两种:一种是隐式调用,一种是显示调用。
1、隐式调用:这种调用方式需要把产生动态连接库时产生的.LIB文件加入到应用程序的工程中。
2、显式调用 :这种调用方式是指在应用程序中用Load Library或MFC提供的AfxLoadLibrary显式的将自己所做的动态连接库调进来,并指定DLL的路径作为参数。
动态调用DLL函数例子
#include <stdio.h>
#include <Windows.h>
#include <tchar.h>
typedef int (*lpAddFun)(int ,int);
int main()
{
HINSTANCE hDll; //DLL句柄
lpAddFun addFun; //函数指针
hDll = LoadLibrary(_T("..\\Debug\\dll.dll"));
if (hDll != NULL) {
//addFun = (lpAddFun)GetProcAddress(hDll, "add");
addFun = (lpAddFun)GetProcAddress(hDll, MAKEINTRESOURCEA(1));
if (addFun != NULL) {
int result = addFun(2, 3);
printf("%d\n", result);
}
FreeLibrary(hDll);
}
else{
printf("loadlibrary error!\n");
}
system("pause");
return 0;
}
通过这个简单的例子,我们获知DLL定义和调用的一般概念:
1、DLL中需以某种特定的方式声明导出函数(或变量、类);
2、应用工程需以某种特定的方式调用DLL的导出函数(或变量、类)。
DLL中导出函数的声明有两种方式:
1、在函数声明中加上__declspec(dllexport);
2、采用模块定义(.def) 文件声明,.def文件为链接器提供了有关被链接程序的导出、属性及其他方面的信息。
静态调用例子
#pragma comment(lib,"dllTest.lib")
extern "C" __declspec(dllimport) add(int x,int y);
DLL中类定义实例
point.h
#ifndef POINT_H
#define POINT_H
#ifdef DLL_FILE
class _declspec(dllexport) point //导出类point
#else
class _declspec(dllimport) point //导入类point
#endif
{
public:
float y;
float x;
point();
point(float x_coordinate,float y_coordinate );
};
#endif
point.cpp
point::point()
{
}
point::point(float x_coordinate,float y_coordinate)
{
x = x_coordinate;
y = y_coordinate;
}
main.cpp
#include "stdafx.h"
#include <windows.h>
#include "..\circle.h"
#pragma comment(lib,"dllTest.lib")
int main(int argc, char* argv[])
{
circle c;
point p(2.0,2.0);
c.SetCentre(p);
c.SetRadius(1.0);
printf("area:%f girth:%f",c.GetArea(),c.GetGirth());
return 0;
}