您的位置:首页 > 其它

MFC静态链接库、动态链接库的联系与区别

2013-04-17 16:52 169 查看
静态链接库(lib)与动态链接库(dll)的比较

首先,静态链接库与动态链接库都是共享代码的方式,也可称为程序模块化的方式;

静态链接库:

lib中的指令都被直接包含在最终的EXE中,因此exe运行时不再需要lib文件;

不能再包含其他的动态链接库或者静态库;

动态链接库:

dll与EXE文件独立存在,所以发布EXE时需要同时发布dll文件;

可以再包含其他的动态链接库或者静态库;

建议:

请最好使用动态链接库(dll)进行程序的模块化,静态链接库(lib)过时了(应用程序升级上就能看出其劣势);

常用DLL查看工具

Dumpbin命令 或 VC++ 自带的Depends工具,可以查看某个[dll档的导出信息]或某个[exe调用的dll信息]。

DLL注意事项:

对于DLL的生成:

请谨慎使用exetern “C”;//这种方式可读性虽高,但不支持重载等;【优劣并存】

请不要使用模块定义(.def) 文件;//因为这种方式不够灵活;【目前def过时了】

不要忘了使用__declspec(dllexport) 与 __declspec(dllimport);

对于编译、运行:

请拷贝dll文件,.lib文件,.h文件到exe主目录(只要保证编译时exe能看到dll相关

的信息即可);【通常做法是组织好源代码的层次并设置好project->setting】

对于发布:

dll文件需与exe文件一起发布。

显示(动态)调用方式与隐式(静态)调用方式的比较:

显示(动态)调用方式的特点是完全由编程者用 API 函数加载和卸载 DLL,程序员可以决定 DLL 文件何时加载或不加载,调用方式灵活

  隐式(静态)方式的特点是由编译系统完成对DLL的加载和应用程序结束时 DLL 的卸载。静态调用方式简单易用,但不如动态调用方式灵活。

建议:

所谓的显、隐就是针对LoadLibrary (“.dll”)而言的;

请最好使用隐式(静态)方式,因为dll导出接口没用extern “C” 修饰的情况下,显示

(动态)调用可读性极差;而不论是否使用过extern “C”,隐式调用的接口名都与dll接口定义相同。

静态链接库、动态链接库、MFC的联系与区别:

使用静态链接库 还是 动态链接库 是一回事,用不用MFC又是另一回事!换句话说就是lib和dll都能使用MFC。

三类动态链接库的比较:

Non-MFC:

不采用MFC类库编写,而是采用标准C风格,导出的dll接口与标准C函数类似;

可被MFC或非MFC程序调用;

总结:(一般规则是:当程序不涉及MFC时创建该类型的dll)

Regular-MFC:

与下面的Extension-MFC类似,采用MFC类库编写,最明显的特点就是包含有一个

CwinApp的派生;

在导出的dll接口中可以使用MFC的类库,但接口本身不能是MFC类或其派生类;

它又可分为静态链接到MFC的规则dll(using MFC in static library)与动态链接(共享)到

MFC的规则dll(using MFC in shared dll);

可被任何支持DLL的语言调用(前提是要采用_stdcall约定);【我不想关心调用约定】

总结:(好处是可以在dll接口中使用MFC类库)【可使用但不可导出MFC】

Extension-MFC:

采用MFC类库编写;

不仅dll接口中可以使用MFC的类库,导出的接口本身也可以是MFC类或其派生类,常用其来增强MFC的现有功能;

只能被MFC程序调用;

总结:(好处是可以用来增强MFC类库的现有功能)

两种规则DLL(Regular-MFC DLL)的比较:

静态链接到MFC的规则dll(using MFC in static library):

DLL接口中默认就使用DLL自己的资源,因此不需要进行模块的资源句柄切换;

使用这种方法生成的规则DLL较大,因为代码可能会重复包含;

总结:(好处是不需模块的资源句柄切换,但dll通常较大)

动态链接(共享)到MFC的规则dll(using MFC in shared dll):

DLL接口中默认使用的是exe的资源,所以,在DLL 接口中为了使用DLL它自己的资源或是为了解决资源重复问题(当DLL和主应用程序中存在相同ID的资源时),必须进行模块的资源句柄切换。

总结:(好处是dll通常较小,但必须进行模块的资源句柄切换)

动态链接(共享)到MFC的规则dll(using MFC in shared dll)时[b]进行模块资源句柄切换的两种方法:[/b]

1. dll接口函数中完成资源模块的切换工作:

//dll接口函数中切换

extern CSharedDllApp theApp;

void ShowDlg(void)

{

//状态变更

HINSTANCE save_hInstance = AfxGetResourceHandle();

AfxSetResourceHandle(theApp.m_hInstance);

CDialog dlg(IDD_DLL_DIALOG);//dll资源

dlg.DoModal();

//状态还原

AfxSetResourceHandle(save_hInstance);

//在此处再进行操作针对的将是应用程序的资源

CDialog dlg1(IDD_DLL_DIALOG);// 应用程序的资源

dlg1.DoModal();

}

在应用程序需要的地方完成切换工作:

//应用程序中切换

void CSharedDllCallDlg::OnCalldllButton()

{

//获取EXE模块句柄

HINSTANCE exe_hInstance = GetModuleHandle(NULL);

//获取DLL模块句柄

HINSTANCE dll_hInstance = GetModuleHandle("SharedDll.dll");

AfxSetResourceHandle(dll_hInstance); //切换状态

ShowDlg(); //此时显示的是DLL的对话框

AfxSetResourceHandle(exe_hInstance); //恢复状态

ShowDlg(); //此时显示的是exe的对话框

}

关于DllMain的说明:

对于No-Mfc的dll及 Extension-Mfc的dll,由MFC自动提供一个;

对于Regular-Mfc,没有定义DllMain时编程环境会自动调用一个默认版本;

总结:(也不是没有用处,在DllMain中可以作一些初始化或者是资源回收等工作)

关于lib库文件的说明:

->>何时用到lib库文件

如果程序中采用隐式(静态)调用dll的话,编译时会需要lib库文件。

动态链接库或静态链接库在exe最终发布时都不需要.lib,.lib只可能在编译期用到。

->>关于将.lib文件导出到特定目录:

"project"-> "settings"-> general-> output files 里面设置;

还可以在Pre-link step和Post-build step属性页里增加命令将文件拷贝到相应的目录,如:

copy debug\my.lib (特定目录)\my.lib

copy debug\my.dll (特定目录)\my.dll

参考:http://topic.csdn.net/t/20041222/15/3667256.html

我采用的Post-build step。编辑copy命令行时要注意,它不支持/而只能用\;

另外还要保证指定的copy目录是存在的,否则编译会出错,它不会给你自动创建。

->>怎样指明lib库文件的位置给linker

若采用隐式调用,链接时需要指明lib的位置,有两种方法:

1) 使用 #pragma comment(lib,"XX.lib");

2) project->setting->LINK选项卡中的Object/Library modules:填写lib文件的路径;或tools->Options->Directories内设置inc和lib的路径;

//比如dll文件为DllClass.dll,则填写 Release/DllClass.lib(此处仅是示例,请注意目录)

前者比后者好的原因是当源文件搬迁给其他用户时,人家不用再去设置Project->setting...

关于纯资源dll:

编写“纯资源dll”:http://hi.baidu.com/pop1210/blog/item/144192b5c6d867da36d3caa5.html

编写“纯资源dll”之二:http://hi.baidu.com/pop1210/blog/item/39a76acc5b1cf10400e92830.html

调用约定, Def文件:

一些调用约定对dll的影响,用Def导出(过时)什么的,不想搞了,否则搞复杂了都。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: