1 用VC建立DLL動態連線庫
1.1 建立dll專案
然後選擇“一個空的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”檔案中實現三個介面函式:
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++呼叫顯式連結
新建一個Win32的控制檯程式進行顯式呼叫:
1. 新建“dllConsoleEvident”的Win32控制檯程式專案
2. 新建cpp檔案“dllConsoleEvident.cpp”
3. 將在第一節中,在Debug目錄下編譯生成的“dllDemo.dll”(顯式呼叫時只需要這一個檔案就夠了)檔案複製到“dllConsoleEvident”專案下的Debug資料夾根目錄下
4. 在“dllConsoleEvident.cpp”檔案中編寫以下程式碼對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控制檯程式)
新建一個Win32控制檯程式演示靜態呼叫
1. 利用嚮導新建“dllConsoleStaticDemo”的空工程
2. 將“dllDemo.dll”和“dllDemo.lib”檔案複製到Debug目錄下,並在專案中包含“dllDemo.lib”檔案(或者),否則會出現dll函式找不到的連線錯誤
3. 新建“dllConsoleStaticDemo.cpp”檔案,並寫入如下程式碼:
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視窗程式)
新建一個MFC基本對話方塊視窗程式進行呼叫:
1. 利用嚮導建立一個MFC基本對話方塊
2. 將“dllDemo.dll”和”dllDemo.lib”檔案複製到本專案的Debug目錄下,在VC工作空間的檔案檢視下面將”dllDemo.lib”新增到專案中
3. 在“dllMfcDemoDlg.h”標頭檔案中的前面對來自外部的dll函式進行宣告
//
#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()的事件響應函式體,編寫呼叫程式碼:
{
// 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:
1. 用Visual Studio建立一個控制檯程式
2. 將“dllDemo.dll”檔案複製到專案的Debug目錄下面
3. 在“Program.cs”中編寫如下程式碼
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專案後,並寫好相應的實現程式碼,點選“執行”,會彈出現在的對話方塊:
然後瀏覽,找到一個呼叫了此dll檔案的執行檔案“*.exe”檔案,然後就可以對dll檔案進行斷點除錯了。
這個“*.exe”檔案可以是任何平臺的,C++也可以,C也可以,C#也可以,只要這個執行檔案呼叫了dll檔案中的函式即可。
如果想更換除錯的“*.exe”檔案,可以在“工程-》設定”對話方塊中的“除錯”選項卡進行設定,瀏覽找到使用者需要的“*.exe”檔案
說明:以VC++環境中呼叫此dll為例,執行dllDemo專案,然後會呼叫“*.exe”檔案,如果此exe檔案含有原始檔,而且剛好在原始檔的Debug目錄下面,那麼,可以同時在exe檔案的原始檔中設定斷點,進行dll和呼叫dll兩個程式的聯調。(好像跨語言呼叫的時候不能進行聯調,筆者只在C++互相呼叫的時候聯調成功過,但C#呼叫的時候沒有聯調成功,這個問題有待解決)
4. DLL返回資料型別探究
目前寫的DLL函式反返回值還僅限於整形,還沒有嘗試其它特殊型別的返回值。更豐富的返回值型別,還要今後慢慢學習和研究。