分享

如何将MFC生成的exe转换为DLL

 Kenshin0_0 2016-11-01

    最近因为项目需要,需要将之前生成的exe在另一个大的项目中调用,因此需要将当前的项目转化为dll。

    之前虽然经常使用dll和Lib,,但却没有亲身尝试生成,对于格式和流程不是很清楚,借机学习了一下。

    参考和查阅了很多帖子,比如

    http://blog.csdn.net/yanbdsky/article/details/4587813 

    http://topic.csdn.net/u/20100727/11/13a60518-7710-44a0-857e-cadd12da7524.html

    还有很多类似的,总之大致就两种思路,虽然我不知道两种在具体实现上有什么异同,现将他们过程介绍一下。

    介绍之前,简要说明一下我的需求和背景,手上的这个项目是基于MFC的一个对话框工程,框架很简单,其中大量引用和调用VTK和OpenCV的函数,还有一些控件操作,屏幕交互,计算分析等。最终希望生成一个dll,提供一个函数接口,调用该函数弹出设计的对话框程序,之所以没有一开始就采用dll,主要是因为对方的需求突然有变。

    方案一:新建一个DLL工程,比如MyDLL,将原工程中的*.h 和 *.cpp文件复制到新建的工程目录下,并添加到工程中。同样的方式导入res文件,不用再去建一遍对话框。我的做法是,新建的工程和原工程同名,然后仅在MyDLL.h中添加相应的头文件,最关键的一步是添加dll函数接口:

     在MyDLL.h中添加

      extern 'C' __declspec(dllexport) void ShowDentalViewDlg(void);// 'C'很必要,多个教程中强调,不加的话,由于C++编译器为函数添加类型名,可能导致在其他程序中调用无法找到对应的函数

     然后在MyDLL.cpp中实现它:

     extern 'C' __declspec(dllexport) void ShowDentalViewDlg(void)
     {

            CDentalViewDlg dlg;
           dlg.DoModal();

      }

     不用多解释,CDentalViewDlg 就是我想调出的对话框类。

     编译后可以再debug文件夹下找到对应工程的dll和lib文件。

     然后可能你会说之后就是调用了啊,我原来也是这么做的,但是这却让我绕了很大的圈,调用失败后只是一味地怀疑这种方法无效,去忽略了一个非常关键的问题,我生成的dll和lib参考完整吗?很多人压根就不会想到之前exe下没问题的程序,生成dll和lib怎么会有参考不完整问题呢?这个问题我遇到了,虽然我不知道为什么。下面说说如何检查生成的dll的参考完整性。

     我用的是VC自带的工具depends.exe, 很简单,打开dll文件后,可以看到其参考的dll还有其接口函数。我发现之所以我生成的dll和lib在测试程序中调用失败,是因为生成的dll中参考dll中有黄颜色的不完整项,因为我大量调用VTK和Opencv,而它们又调用很多其他的库,最终缺少msvcr80.dll和msvcp80.dll,解决办法自然是添加这两个dll了,好不容易找到了,我不知道原先exe下是怎么找到它们的,因为在系统盘中好像我没有发现这两个文件的踪迹。看到黄色dll都没了,心里好不欣慰。

    生成完整的dll和lib 后,最后一步就是测试了,这一步只要按部就班就好了。首先将lib和dll拷贝到测试工程中,添加它们的路径(这一步有多种方式:可以像添加VTk库一样,也可以用#pragma comment(lib,'***'))。不要忘了最重要的一步,拷贝并添加所有dll中用到的*.h文件到测试程序。最后为测试控件添加响应函数:

void CTestDLLDlg::OnBnClickedButton1()
{
   ShowDentalViewDlg();
   #pragma comment(lib,'..\\debug\\DentalView')//这里冗余了,其实就是给定lib所在路径,相对和绝对都可以

}

这样就可以编译、测试了。

 

第二种方案

直接在原工程中修改配置,在   项目/项目属性/配置属性/常规/配置类型中将.exe改为dll,添加接口函数(在项目的.h中声明在.cpp中定义):

extern 'C' void show()
{

 AFX_MANAGE_STATE(AfxGetStaticModuleState());
 CDentalViewDlg * dlg = new CDentalViewDlg();

 dlg->DoModal();
};

然后编译,这次可以看到在debug文件夹中相比方案一少了.lib文件。

其调用方式也不太一样:

void CTestDLLDlg::OnBnClickedButton1()
{

 typedef void (*Msgs)(void);

 HINSTANCE h = ::LoadLibrary(L'DentalView.dll');

 if (h == NULL) return;


 Msgs dllfun = (Msgs)::GetProcAddress(h, 'show');

 dllfun();

 ::FreeLibrary(h);

}

这里要注意,如前面参考网页所述,需将工程的.cpp中的InitInstance()函数中调用dlg.DoModel()相关语句注释掉,以便其不在导入dll时就弹出对话框。

但这个方法我遇到一个问题,LoadLibrary(L'DentalView.dll')返回值总是为null,目前还在测试,有待进一步补充。

 

以上就是自己对MFC 的exe转dll的尝试和学习心得,有其他方法的欢迎补充。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多