mfc导出dll(一)

1、例子

以下内容来自Creating and consuming MFC DLLs for Beginners

1.1、创建用于导出dll的工程

1.1.1、创建项目

A. 选择文件->新建->项目
B. 选择模板MFC DLL,名称填写为MyDll,如图1.1。

图 1.1

C. 选择使用共享MFC DLL的规则DLL,如图1.2。

图 1.2

1.1.2、添加要导出的类与函数

A. 类视图中,选中MyDll,右键->添加->,选择C++ 类,如图1.3。

图 1.3

B. 类的名称为CMyClass,如图1.4。

图 1.4

C. 类视图中,选中CMyClass,右键->添加->函数

D. 返回类型CString,函数名SayHello,参数CString strName,如图1.5。

图 1.5

E. 实现SayHello

// CMyClass.cpp

CString CMyClass::SayHello(CString strName)
{
    return "Hello " + strName; 
}

1.1.3、将类中的函数声明为要导出的类型

CMyClass()~CMyClass()SayHello()添加__declspec(dllexport)

// CMyClass.h 

class CMyClass
{
public:
    __declspec(dllexport)  CMyClass(void);
    __declspec(dllexport)  ~CMyClass(void);
    __declspec(dllexport)  CString SayHello(CString strName);
};

1.1.4、编译

选择Release模式,进行编译,得到MyDll.dllMyDll.lib

如果有错误,可以参考以下解决方案: 报错: **1 error C2678: 二进制“+”: 没有找到接受“const char [7]”类型的左操作数的运算符(或没有可接受的转换) f:\MyDll\MyDll\MyClass.cpp 14**。 解决: 选中**MyDll**,右键->**属性**->**配置属性**->**常规**->**字符集**->**使用多字节字符集**。

1.2、创建调用dll的工程

1.2.1、创建项目

A. 选择文件->新建->项目
B. 选择模板MFC 应用程序,名称填写为TestDLL,如图1.6。

图 1.6

C. 应用程序类型选择基于对话框,点击完成,如图1.7。

图 1.7

1.2.2、修改UI界面

A. 点击Static Text控件,在属性窗口中修改Caption的值为"Enter your name and click ok"。

B. 在工具箱窗口中,拖动一个Edit Control 控件到界面上,如图1.8。

图 1.8

1.2.3、给Edit Control关联一个变量

A. 选中Edit Control控件,右键->添加变量
B. 变量类型填写CString,变量名为m_edit,类别为Value,如图1.9。

图 1.9

1.2.4、给Button绑定一个单击事件

A. 选中确定按钮,双击,自动创建新函数void CTestDLLDlg::OnBnClickedOk()

1.2.5、导入dll

A. 在工程目录下创建include文件夹和lib文件夹,如图1.10。

图 1.10

MyClass.h复制到include文件下,将MyDll.lib复制到lib文件夹下

B. 切换解决方案配置为Release

C. 选中TestDLL,右键->属性->C/C++->常规->附加包含目录,添加../include,如图1.11。

图 1.11

D. 选中TestDLL,右键->属性->链接器->常规->附加库目录,添加../lib,如图1.12。

图 1.12

1.2.6、添加头文件和lib文件

// TestDLLDlg.h

#include "MyClass.h"

#pragma comment(lib, "MyDll.lib")

1.2.7、创建MyClass对象

在CTestDLLDlg类中添加CMyClass objMyClass

// TestDLLDlg.h

class CTestDLLDlg : public CDialog
{
// 构造
public:
	CTestDLLDlg(CWnd* pParent = NULL);	// 标准构造函数
    CMyClass objMyClass; 

1.2.8、实现确定单击事件OnBnClickedOk

//  TestDLLDlg.cpp

void CTestDLLDlg::OnBnClickedOk()
{
    // TODO: 在此添加控件通知处理程序代码
    UpdateData(true);
    CString strResult = objMyClass.SayHello(m_edit);
    AfxMessageBox (strResult);
    //OnOK();
}

1.3、编译运行

A. 选择Release模式,进行编译,得到TestDLL.exe

如果有错误,可以参考以下解决方案: 报错: **1>TestDLLDlg.obj : error LNK2001: 无法解析的外部符号 "public: class ATL::CStringT > > __thiscall CMyClass::SayHello(class ATL::CStringT > >)" (?SayHello@CMyClass@@QAE?AV?$CStringT@_WV?$StrTraitMFC_DLL@_WV?$ChTraitsCRT@_W@ATL@@@@@ATL@@V23@@Z) 1>F:\QAQ\practice\TestDLL\Release\TestDLL.exe : fatal error LNK1120: 1 个无法解析的外部命令**。 解决: 选中**TestDLL**,右键->**属性**->**配置属性**->**常规**->**字符集**->**使用多字节字符集**。

B. 将MyDll.dll拷贝TestDLL.exe到同级目录下,单击TestDLL.exe运行,如图1.13。

图 1.13

2、知识点

2.1、MFC的dll工程

  • MFC编译dll在创建项目时已经提供了模板MFC DLL

  • MFC DLL模板中有共享MFC DLL的规则DLL带静态链接MFC的规则DLLMFC扩展DLL三种。选择共享MFC DLL的规则DLL后,在运行该dll时,机器必须安装MFC库。选择带静态链接MFC的规则DLL,在运行该dll时不需要安装MFC库。

2.2、导出dll函数的两种方式

  • 方法一:函数声明时标注_declspec(dllexport)表示导出函数

例如:

__declspec(dllexport)  CString SayHello(CString strName);
  • 方法二:.def文件中标注导出函数名

例如:

; DLL.def : 声明 DLL 的模块参数。

LIBRARY      "DLL"

EXPORTS
    ; 此处可以是显式导出
SayHello

2.2、_declspec(dllexport)与.def文件的异同

  • 对于VC++程序调用dll两者没有区别,对于其他(例如VB)程序调用dll最好用.def方式。

  • 对于类的导出,往往使用_declspec(dllexport)方式

2.3、__declspec(dllexport)和__declspec(dllimport)的区别

该部分摘自[__declspec(dllexport) & __declspec(dllimport)](http://www.cnblogs.com/xd502djj/archive/2010/09/21/1832493.html)
  • __declspec(dllexport)
    声明一个导出函数,是说这个函数要从本DLL导出。我要给别人用。一般用于dll中。
    省掉在DEF文件中手工定义导出哪些函数的一个方法。当然,如果你的DLL里全是C++的类的话,你无法在DEF里指定导出的函数,只能用__declspec(dllexport)导出类。

  • __declspec(dllimport)
    声明一个导入函数,是说这个函数是从别的DLL导入。我要用。一般用于使用某个dll的exe中。
    不使用 __declspec(dllimport) 也能正确编译代码,但使用 __declspec(dllimport) 使编译器可以生成更好的代码。编译器之所以能够生成更好的代码,是因为它可以确定函数是否存在于 DLL 中,这使得编译器可以生成跳过间接寻址级别的代码,而这些代码通常会出现在跨 DLL 边界的函数调用中。但是,必须使用 __declspec(dllimport) 才能导入 DLL 中使用的变量。

2.4、_declspec(dllexport)兼容C的通常使用方式

A. 宏定义__declspec(dllexport)

#ifdef TOOL_EXPORTS  
#define TOOL_API  extern "C" __declspec(dllexport)  
#else  
#define TOOL_API  extern "C" __declspec(dllimport)  
#endif  

TOOL_API int   Test(int a,int b);

B. 在工程中定义宏TOOL_EXPORTS

点击工程,右键属性->C/C++->预处理器->预处理器定义,添加TOOL_EXPORTS,如图2.1

图 2.1
posted @ 2017-09-27 15:03  白应非  阅读(4186)  评论(0编辑  收藏  举报