VC++的DLL應用(含Demo演示)

weixin_33912246發表於2012-06-05
在大學大一的時候學的是C,然後後來大二的時候專業又開了C++這個課程,然後再後來自己又自學了一點VC++,大三的時候也試著編寫過一個MFC的最簡單的視窗程式。到大四的時候,自己又做了一個GIS的專案,是用C#.NET來編寫的,然後發現C#上手好容易,而且還大部分語法規則都沿用了C,C++的習慣,於是覺得C++實在是沒有一點優勢可言啊。但這個暑假的實習經歷又改變了我的觀點:C++在寫視窗程式雖然麻煩,但是卻什麼能做,而且對比C#來說,對執行環境的要求不高,不用像C#程式在安裝之前還要安裝100M多的執行.NET環境。C++和C#各有優缺,目前我對它們倆的定位是:C++用來寫一些底層的程式,比如驅動,或者是一些演算法型別的函式介面,然後用C#來呼叫這些介面並進行介面設計。如何函式的實現跨語言呢?顯然DLL是個很重要的內容,故在此對VC++的DLL模組進行介紹。

1 用VC建立DLL動態連線庫

1.1 建立dll專案

clip_image002

然後選擇“一個空的dll工程”,然後點選“確定”便完成了“建立dll專案”的流程。

1.2 為dll專案編寫原始檔

新建兩個檔案:dllDemo.h, dllDemo.cpp

在標頭檔案”dllDemo.h”中宣告三個介面函式:

 

extern "C" _declspec(dllexport) int Sum(int a,int b);//加法函式。 extern "C" _declspec(dllexport) int Max(int a, int b);//取較大值函式 extern "C" _declspec(dllexport) int Min(int a, int b);//取較小值函式

 

然後在“dllDemo.cpp”檔案中實現三個介面函式:

#include "dllDemo.h"
extern "C" _declspec(dllexport)int Sum(int a, int b)
{
return a+b;
}
extern "C" _declspec(dllexport)int Max(int a, int b)
{
if(a>=b)return a;
else
return b;
}
extern "C" _declspec(dllexport)int Min(int a, int b)
{
if(a>=b)return b;
else
return a;
}

1.3 生成dll檔案

編譯原始檔,如果沒有出現錯誤提示,那麼,在專案檔案根目錄的Debug資料夾內會生成一個dll檔案“dllDemo.dll”。

2 DLL呼叫

2.1 用C++呼叫顯式連結

clip_image004

新建一個Win32的控制檯程式進行顯式呼叫:

1. 新建“dllConsoleEvident”的Win32控制檯程式專案

2. 新建cpp檔案“dllConsoleEvident.cpp”

3. 將在第一節中,在Debug目錄下編譯生成的“dllDemo.dll”(顯式呼叫時只需要這一個檔案就夠了)檔案複製到“dllConsoleEvident”專案下的Debug資料夾根目錄下

4. 在“dllConsoleEvident.cpp”檔案中編寫以下程式碼對dll中的函式進行顯式呼叫

//動態載入DLL檔案
#include <iostream.h>
#include
<windows.h>
void main(void)
{
typedef
int(*pMax)(int a,int b);//函式指標
typedef int(*pMin)(int a,int b);
pMax Max
=NULL;
pMin Min
=NULL;
HINSTANCE hDLL;
hDLL
=LoadLibrary("MyDll.dll");//載入動態連結庫MyDll.dll檔案;
Max=(pMax)GetProcAddress(hDLL,"Max");
Min
=(pMin)GetProcAddress(hDLL,"Min");
if (Max)//如果取出函式成功,則執行下面的語句
{
int A=Max(5,8);
cout
<<"比較的結果為"<<A;
}
if (Min)
{
int B=Min(5,8);
cout
<<"比較的結果為"<<B;
}
FreeLibrary(hDLL);
//解除安裝MyDll.dll檔案;
}

2.2 用C++隱式連結(Win32控制檯程式)

clip_image006

新建一個Win32控制檯程式演示靜態呼叫

1. 利用嚮導新建“dllConsoleStaticDemo”的空工程

2. 將dllDemo.dll”和“dllDemo.lib檔案複製到Debug目錄下,並在專案中包含“dllDemo.lib”檔案(或者),否則會出現dll函式找不到的連線錯誤

3. 新建“dllConsoleStaticDemo.cpp”檔案,並寫入如下程式碼:

extern "C"_declspec(dllimport) int Sum(int a,int b);
extern "C"_declspec(dllimport) int Max(int a,int b);
extern "C"_declspec(dllimport) int Min(int a,int b);
#include
<iostream.h>
void main()
{
int c=Sum(4,5);
c
=Max(5,6);
c
=Min(5,6);
cout
<<"Hello,dllConsoleTest~!";
}

4.通過斷點,可以看到dll函式呼叫成功

這種方式的靜態呼叫的特點是:在程式一開始執行的時候,就將dll檔案全部載入到程式中,不會釋放。

2.3 用C++隱式連結(MFC視窗程式)

clip_image008

新建一個MFC基本對話方塊視窗程式進行呼叫:

1. 利用嚮導建立一個MFC基本對話方塊

2. 將dllDemo.dll”和”dllDemo.lib”檔案複製到本專案的Debug目錄下,在VC工作空間的檔案檢視下面將”dllDemo.lib”新增到專案中

3. 在“dllMfcDemoDlg.h”標頭檔案中的前面對來自外部的dll函式進行宣告

// dllMfcDemoDlg.h : header file
//
#if
#define AFX_DLLMFCDEMODLG_H__E358B876_D188_48FD_8D83_794309C885A9__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
/////////////////////////////////////////////////////////////////////////////
// CDllMfcDemoDlg dialog
extern "C"_declspec(dllimport) int Sum(int a,int b);
extern "C"_declspec(dllimport) int Max(int a,int b);
extern "C"_declspec(dllimport) int Min(int a,int b);
……

4.在窗體介面上,雙擊“確定”按鈕,進入到OnOk()的事件響應函式體,編寫呼叫程式碼:

void CDllMfcDemoDlg::OnOK()
{
// TODO: Add extra validation here
int c=Sum(4,5);
c
=Max(5,6);
c
=Min(5,6);
CDialog::OnOK();
}

通過設定斷點單步執行就可以看到dll檔案中的函式已經被成功呼叫了。

2.4 用C#跨語言呼叫

C#控制檯程式呼叫VC++建立一個dll:

clip_image010

1. 用Visual Studio建立一個控制檯程式

2. 將“dllDemo.dll”檔案複製到專案的Debug目錄下面

3. 在“Program.cs”中編寫如下程式碼

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;//引入dll檔案中的函式
namespace ConsoleDllDemo
{
class Program
{
//引入dll檔案中的函式
[DllImport("dllDemo.dll")]
private static extern int Sum(int a, int b);
[DllImport(
"dllDemo.dll")]
private static extern int Max(int a, int b);
[DllImport(
"dllDemo.dll")]
private static extern int Min(int a, int b);
static void Main(string[] args)
{
int a = Sum(3, 5);
Console.WriteLine(a);
Console.WriteLine(Max(
5,10));
Console.WriteLine(Min(
12,25));
Console.ReadKey();
//要按鍵才退出。
}
}
}

然後斷點單步執行,便可以看到呼叫函式的結果了。

3 dll除錯方法

在建立了dll專案後,並寫好相應的實現程式碼,點選“執行”,會彈出現在的對話方塊:

clip_image012

然後瀏覽,找到一個呼叫了此dll檔案的執行檔案“*.exe”檔案,然後就可以對dll檔案進行斷點除錯了。

這個“*.exe”檔案可以是任何平臺的,C++也可以,C也可以,C#也可以,只要這個執行檔案呼叫了dll檔案中的函式即可。

如果想更換除錯的“*.exe”檔案,可以在“工程-》設定”對話方塊中的“除錯”選項卡進行設定,瀏覽找到使用者需要的“*.exe”檔案

clip_image014

說明:以VC++環境中呼叫此dll為例,執行dllDemo專案,然後會呼叫“*.exe”檔案,如果此exe檔案含有原始檔,而且剛好在原始檔的Debug目錄下面,那麼,可以同時在exe檔案的原始檔中設定斷點,進行dll和呼叫dll兩個程式的聯調。(好像跨語言呼叫的時候不能進行聯調,筆者只在C++互相呼叫的時候聯調成功過,但C#呼叫的時候沒有聯調成功,這個問題有待解決)

4. DLL返回資料型別探究

目前寫的DLL函式反返回值還僅限於整形,還沒有嘗試其它特殊型別的返回值。更豐富的返回值型別,還要今後慢慢學習和研究。

相關文章