动态链接库学习笔记

作者在 2014-03-19 17:44:09 发布以下内容

动态链接库有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;
}










C++ | 阅读 1749 次
文章评论,共0条
游客请输入验证码
最新评论