您的位置:首页 > 其它

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

2013-10-22 09:37 204 查看



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

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

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

/article/9260948.html

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的尝试和学习心得,有其他方法的欢迎补充。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: