1. 程式人生 > >MFC動態連結庫呼叫詳解

MFC動態連結庫呼叫詳解

MFC動態連結庫的呼叫,有好多種方式,這裡只介紹一種簡單的呼叫的方式,只需要把動態連結庫編譯後的.dll檔案放到呼叫介面的Debug下面。再在介面需要呼叫動態連結庫裡新增相關函式就行了。找了好多資料,發現沒有詳細的介紹,下面就是從動態連結庫建立開始,一點點詳細的介紹。

首先是,動態連結庫的建立。我們這裡講的是MFC的標準庫的建立。用的是vs2010。
我們建立一個名為TestDLL的動態連結庫。
這裡寫圖片描述

然後,我們這裡實現一個小程式,在動態連結庫裡返回四個點,用來畫一個矩形。

首先,我們寫的是動態連結庫裡的內容,先不考慮介面的問題。

我們在動態連結庫裡新建一個類,用來儲存矩形的四個點。注意,這裡的類名不要起的很常見,例如,CDrawRect這樣的類,因為很有可能和MFC內部已有的類衝突,從而會出現顯示呼叫不明確的情況。
這裡寫圖片描述

上面出現的warning“找不到符號唯一的匹配項錯誤”,是因為在mfc中已經有定義。

這裡寫圖片描述

所以,我們起類名字時,要注意這點。
這裡寫圖片描述

然後,我們在新建的類中新增一個公有成員函式,名字叫做

CPoint* GetPoint();

這樣,就建立一個函式,裡面返回的是矩形的點的陣列的指標。這樣,就能通過地址來呼叫數組裡面的一串值了。

在.cpp裡,寫下:

CPoint* CDrawRectPoint::GetPoint()
{
    CPoint getPoint[4];

    getPoint[0].x=100;
    getPoint[0].y=100;
    getPoint[1
].x=100; getPoint[1].y=500; getPoint[2].x=500; getPoint[2].y=500; getPoint[3].x=500; getPoint[3].y=500; return getPoint; }

這裡,我們為了養成一個良好的習慣,要把動態連結庫的介面專門在一個派生類中寫出來,這樣,就會在匯出的時候,我們只需要對介面進行處理就好了。並且,在提交專案時,也只需要提供.dll和介面類就好,可以有效的保證自己程式碼的安全和核心程式碼的利益。

於是,我們新建一個派生類,從CDrawRectPoint類裡派生出來一個類,名字叫做CDrawRectPointIO。

#include "drawrectpoint.h"

class CDrawRectPointIO:
    public CDrawRectPoint
{
    //說明:沒有把建構函式解構函式寫出來
    CPoint* GetPoint();
}

在.cpp裡:

CPoint* CDrawRectPointIO::GetPointIO()
{
    return GetPoint();
}

好了,上面是動態連結庫裡的內容已經寫出來,下面是寫出動態連結庫的調出。

在CDrawRectPointIO.h檔案中,在最開始的部分,加上:

//即把匯出的函式宣告為全域性的,並且宣告為外部可呼叫
extern "C" __declspec(dllexport)CPoint* __stdcall GetPointIO();

這裡寫圖片描述

然後,再在原始檔裡的.def檔案裡,新增匯出的函式的名稱,因為這個是不加變數,只有函式名稱的,所以,這也是前面提到的為什麼函式命名時儘量不要用太常見的函式名的原因。

這裡寫圖片描述

之後是除錯,在Debug裡得到.dll。到這裡就是動態連結庫的匯出過程。

然後是動態連結庫在介面中的呼叫。

新建一個MFC單文件類。名字叫做TestEXE,設定成MFC標準。這裡為了方便畫,直接就在OnDraw(CDC*pDC)函式裡寫了,實際上不推薦在這個函式裡呼叫動態連結庫,因為系統裡會不斷的自動重新整理OnDraw()函式,所以,為了安全起見,我們最好不要用在OnDraw()函式裡寫。這裡,我們用一個控制變數來控制是否啟用動態連結庫。

首先,是建立之後,F5除錯程式。生成Debug,把前面動態連結庫生成的.dll複製貼上到介面的Debug裡。

在資源視圖裡的Menu裡新增選單欄,並把ID修改。類嚮導到view裡。

這裡寫圖片描述

在view.h裡新增成員變數,int m_nControl;在建構函式裡初始化為0。

在view.cpp裡,對剛才新增的OnRect()函式裡,新增控制變數。

void CTestEXEView::OnRect()
{
    // TODO: 在此新增命令處理程式程式碼
    m_nControl = 1;
    Invalidate();
}

下面先是對動態連結庫的呼叫,在view.cpp裡,在檔案頭下新增如下:

typedef CPoint*(WINAPI *dllDraw)();

在OnDraw裡新增:

if(1 == m_nControl)
    {
        HINSTANCE hDLL; 
        hDLL=LoadLibrary("TestDLL.dll");//載入動態連結庫MyDll.dll檔案;
        if(hDLL == NULL)  
        {  
            MessageBox("無法載入dll\n");  
            FreeLibrary(hDLL);  
        }

        dllDraw DrawNew;
        DrawNew=(dllDraw)GetProcAddress(hDLL,"GetPointIO");

        if(DrawNew == NULL)  
        {  
            MessageBox("第二步無法載入dll\n");  
            FreeLibrary(hDLL);   
        } 

        CPoint *m_point = new CPoint[4];
        m_point = DrawNew();

        CPoint point[4];
        for(int i=0;i<4;i++)
        {
            point[i]=m_point[i];
        }

        pDC->MoveTo(m_point[0]);
        pDC->LineTo(m_point[1]);
        pDC->LineTo(m_point[2]);
        pDC->LineTo(m_point[3]);
        pDC->LineTo(m_point[0]);

        FreeLibrary(hDLL);
        m_nControl=0;
        delete []m_point;
        m_point = NULL;
    }

最後得到結果如圖:

這裡寫圖片描述

以上就是全部內容了。