1.1 創建dll項目
1.2 為dll項目編寫源文件
頭文件dllDemo.h
extern?"C"?_declspec(dllexport)?int?Max(int?a,?int?b);//取較大值函數
extern?"C"?_declspec(dllexport)?int?Min(int?a,?int?b);//取較小值函數

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”。
調用
新建了個MFC單對話框項目,
將“dllDemo.dll”和”dllDemo.lib”文件復制到本項目的Debug目錄下,
在VC工作空間的文件視圖下面將”dllDemo.lib”添加到項目中
在對話框頭文件添加引用:

//
#pragma?once
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);
//?CFileOperDlg?對話框
class?CFileOperDlg?:?public?CDialog
{
//?構造
public:
????CFileOperDlg(CWnd*?pParent?=?NULL);????//?標準構造函數
//?對話框數據
????enum?{?IDD?=?IDD_FILEOPER_DIALOG?};
????protected:
????virtual?void?DoDataExchange(CDataExchange*?pDX);????//?DDX/DDV?支持
//?實現
protected:
????HICON?m_hIcon;
????//?生成的消息映射函數
????virtual?BOOL?OnInitDialog();
????afx_msg?void?OnSysCommand(UINT?nID,?LPARAM?lParam);
????afx_msg?void?OnPaint();
????afx_msg?HCURSOR?OnQueryDragIcon();
????DECLARE_MESSAGE_MAP()
public:
????CString?m_info;
};
?
調用:
int?c=Sum(4,5);??
//c=Max(5,6);??
//c=Min(5,6);
str.Format("%d",c);
AfxMessageBox(str);
?
調試
直接運行,選擇一個調用dll的exe確定之后,就可以調試了,設置個斷點試試。
?
?
?
參考:
VC++的DLL應用(含Demo演示)
作者:一點一滴的Beer?http://beer.cnblogs.com/
????? 在大學大一的時候學的是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項目
然后選擇“一個空的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中的函數進行顯式調用
?

//動態加載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 !defined(AFX_DLLMFCDEMODLG_H__E358B876_D188_48FD_8D83_794309C885A9__INCLUDED_)
#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();//要按鍵才退出。
}
}
}
?
?
?
然后斷點單步運行,便可以看到調用函數的結果了。
關于DLL的調用的更詳細內容可以參考另外一些文章:
http://dev.firnow.com/course/3_program/c++/cppsl/2008127/97781.html
http://dev.yesky.com/283/2640283_2.shtml
?
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函數反返回值還僅限于整形,還沒有嘗試其它特殊類型的返回值。更豐富的返回值類型,還要今后慢慢學習和研究。等回學校了再研究吧。請見后續文章吧。
?
?
附件:
VC_dll_Realse.rar中是VC編寫DLL并引用DLL的相關源碼文件
CShapr_ConsoleDllDemo.rar中是VS2005編寫的C#引用VC編寫的DLL函數的相關源碼文件
http://files.cnblogs.com/beer/VC_dll_Realese.rar
http://files.cnblogs.com/beer/CSharp_ConsoleDllDemo.rar
------------------------------------------------------------------