MFC静态链接库、动态链接库的联系与区别 | 您所在的位置:网站首页 › 动态链接库的创建方式 › MFC静态链接库、动态链接库的联系与区别 |
静态链接库(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)时进行模块资源句柄切换的两种方法: 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导出(过时)什么的,不想搞了,否则搞复杂了都。 |
CopyRight 2018-2019 实验室设备网 版权所有 |