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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM