长丰县科技创新杜方平:串讲笔记:动态连接库 - molti的专栏 - CSDNBlog

来源:百度文库 编辑:偶看新闻 时间:2024/06/28 10:47:22

动态连接库

1.动态连接库是一些独立的文件,其中包含能被可执行程序其它DLL调用来完成某项工作的函数。只有在其它模块调用动态连接库中的函数时,它才发挥作用。

2.Windows API 中的所有函数都包含在DLL中。 Kernel32.dll,它包含用于管理内存、进程和线程的各个函数;User32.dll,包含用于执行用户界面任务(如窗口的创建和消息的传送)的各个函数;GDI32.dll,它包含用于画图和显示文本的各个函数。

静态库和动态库

1.静态库:函数和数据被编译进一个二进制文件(通常为 .LIB )。 编译连接 .exe 文件时,连接器从库中复制这些函数和数据并把它们和应用程序的其他模块组合起来创建最终的 .exe 文件。
发布时只需发布 .exe 文件而无需提供静态库文件。

2.在使用动态库的时候,往往提供两个文件:一个 引入库( .lib ) 和一个 DLL。引入库包含被DLL导出的 函数和变量的符号名,DLL包含实际地函数和数据。编译连接 .exe 时,只需要链接引入库,运行时再去加载DLL,访问DLL中导出的函数。发布时需要发布DLL。

使用动态连接库的好处

1.可以采用多种语言来编写。( 在VB中调用用VC写的封装了业务逻辑的DLL )。

2.增强产品的功能。
  发布产品的同时发布 dll规范,其他人可以按规范编写dll替换只,以达到功能的增强。例如:skin,替换UI的动态连接库。

3.提供二次开发的平台。

4.简化项目管理。

5.节省磁盘空间和内存。
  如果 .dll 已加载到内存,如果其他程序也需要该模块,则不需要再加载到内存中, x86的页面大小是4KB。

6.有助于资源的共享。 可以编写纯资源的动态连接库,供其他app访问。

7.用助于实现应用程序的本地化。 为每种语言提供只支持这种语言的动态连接库。

动态连接库被多个进程访问

将.DLL 的虚拟内存中的代码页面和数据页面映射到不同进程的地址空间中去。

动态连接库加载的两种方式

1.隐式链接
  ProjectSetting -> Link -> Object/Libary Modules:   =>  dll1.lib(为运行时加载dll提供重定位表)
  #include ".\dll1.h"

  dll1.cpp

#define DLL1_API extern "C"_declspec(dllexport)
#include "dll1.h" //头文件不参与编译,源文件单独编译
#include
#include
int _stdcall add( int a, int b ) { return a + b; }
int _stdcall subtract( int a, int b ) { return a - b; }
/* void MyPoint::output( int x, int y )
{ HWND hwnd = GetForegroundWindow();
  HDC hdc = GetDC( hwnd );
  char buf[20]; memset( buf,0,20);
  sprintf( buf, "x=%d, y=%d", x, y );
  TextOut( hdc, 0, 0, buf, strlen( buf ) );
  ReleaseDC( hwnd,hdc ); } */
 


Depends.exeexe


   
2.显式加载


名字改编:通过模块定义文件解决
EXPORTS
entryname[=internalname] [@ordinal [NONAME]] [PRIVATE] [DATA]

HMODULE LoadLibrary(LPCTSTR lpFileName );FARPROC GetProcAddress( HMODULE hModule, LPCSTR lpProcName ); 

dll2.cpp
int _stdcall add( int a, int b ) { return a + b; }
int _stdcall subtract( int a, int b ) { return a - b; }


dll2.def
LIBRARY dll2
EXPORTS
add
subtract

HINSTANCE hInst;
hInst = LoadLibrary( "dll2.dll" ); //
if( NULL == hInst ) { AfxMessageBox("dll2.dll未成功加载!" ); return; } //
typedef int( _stdcall *ADDPROC )( int a, int b );
ADDPROC ADD = (ADDPROC)GetProcAddress( hInst, "add" ); //
if( !ADD ) { AfxMessageBox( "获取函数地址失败!" ); return; }
CString str;
str.Format( "5 + 3 = %d", ADD( 5, 3 ) );
AfxMessageBox( str );

Note:注意调用约定

DLLMain

BOOL WINAPI DllMain(
    HINSTANCE hinstDLL
    DWORD fdwReason
    LPVOID lpvReserved );

fdwReason:
DLL_PROCESS_ATTACH 1
DLL_THREAD_ATTACH  2
DLL_THREAD_DETACH  3
DLL_PROCESS_DETACH 0

MFC扩展DLL

减少对该module的引用计数

  BOOL FreeLibrary( HMODULE hModule );

 

 

 

 

  dll1.h(供客户使用
#ifdef DLL1_API
#else
#define DLL1_API extern "C" _declspec(dllimport)
#endif
DLL1_API int _stdcall add( int a, int b );
DLL1_API int _stdcall subtract( int a, int b );
/* class DLL1_API MyPoint{ public: void output( int x, int y ); }; */

  _

                            
>dumpbin -exports dll1.dll  
                            


                                   
   >dumpbin -imports TestDll.exe