zoukankan      html  css  js  c++  java
  • 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:MyDllMyDllMyClass.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:QAQpracticeTestDLLReleaseTestDLL.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
  • 相关阅读:
    B站使用总结
    安装国外浏览器的好处
    查看网页源代码
    如何下载bilibili上面的视频
    11.27
    11.26
    11.25
    11.24获取时间
    11.23
    11.21
  • 原文地址:https://www.cnblogs.com/featherw/p/7601754.html
Copyright © 2011-2022 走看看