DLL編程講解
本文介紹一點關于DLL的基礎知識,如果你是系統編程的高手就不要看了。先介紹些DLL的基礎知識。DLL(Dynamic Link Library:動態鏈接庫)其實這個東西就是把一些經常要用的代碼塊編譯完后放在磁盤上,當有應用程序需要其中的功能時,就把DLL文件映射到自己的進程空間中然后根據DLL中的輸出符號來加載其中的功能代碼,完成一定的功能。這就有點像C標準函數庫。
這樣做的好處可用有以下幾點。
1.節省了系統資源。
2.一次編譯,多個進程可用多次調用。
3.就是一個應用程序你可以用C++實現,但C++實現的程序卻可用調用其他語言寫的DLL文件。
下面介紹一下具體的DLL的編寫和調用。
1.DLL的編寫其實很我們正常的應用的程序的編寫基本上是差不多的。
比如有一個功能函數是
int Add(int nLeft ,int nRight)
{
g_nResult = nLeft + nRight;
return g_nResult;
}我們可用把它寫入正常的應用程序,也可用把它直接的寫如DLL文件中。
2.DLL的調用,調用DLL文件有兩種方法一種是顯式的加載和隱式的加載。
下面先來看看隱示的加載DLL。
(需要兩個文件一個DLL.DLL,另一個是install.exe)
我們先來建立一個名為mydll的DLL工程,我用的是VC 6.0。
新件工程->WIN32 Dynamic Link Library。不要選擇MFC的DLL工程。
然后選擇AN EMPTY DLL PROJECT,接下來一路OK。
這樣我們就建立了一個空的DLL工程了。
接下在其中建立mydll.dll和mydll.h文件。
寫下如下代碼:
//
//mydll.h
//首先必須創建一個頭文件,它包含你想要從DLL輸出的函數原型、結構和符號。
//
//DLL的所有源代碼模塊均包含該頭文件,以幫助創建DLL。
#ifdef MYLIBAPI 
#else
#define MYLIBAPI extern"C" __declspec(dllimport)
//這個地方是為了,不改變DLL在被進行C++編譯時改變各種符號
#endif
//變量和函數的聲明
MYLIBAPI int g_nResult;
MYLIBAPI int Add(int nLeft, int nRight);
//---------------------------the end-------------------------

//
//mydll.cpp
//
#include <windows.h>
#include "mydll.h"
#define MYLIBAPI extern "C" __declspec(dllexport)
//函數和變量的具體定義
int g_nResult;
int Add(int nLeft ,int nRight)
{
g_nResult = nLeft + nRight;
return g_nResult;
}
//-----------------------the end---------------------------------編譯這個工程,就可用得到DLL.DLL文件了。
然后建立一個明為“install”的控制臺工程,在其中建立install.cpp和install.h兩個文件。
寫入如下代碼:
//
//install.h
//
//其實這個文件和前面的DLL工程里面的mydll.h文件的是一樣的 
#ifdef MYLIBAPI 
#else
#define MYLIBAPI extern"C" __declspec(dllimport)
//這個地方是為了,不改變DLL在被進行C++編譯時改變各種符號
#endif
//變量和函數的聲明
MYLIBAPI int g_nResult;
MYLIBAPI int Add(int nLeft, int nRight);
//---------------------------the end-------------------------
//
//install.cpp
//
//這個文件是調用DLL內提供的函數的,應用程序。
//
//這個調用方式是一中“隱式的調用”,這種方是從系統默認的幾個路徑去找,DLL文件。
//缺少了程序的靈活性
//
#include <windows.h>
#include "install.h"
#pragma comment(lib,"mydll.lib")
//這個LIB文件是編譯DLL時產生的,在DLL工程的DEBUG文件夾里可用找到。
//mydll.lib里面是DLL文件對外輸出的接口符號
int main()
{
int nLeft =10,nRight = 25;
TCHAR sz[100];
wsprintf(sz,TEXT("%d + %d = %d"),nLeft, nRight,Add(nLeft,nRight));
MessageBox (NULL,sz, TEXT("Last Result"),MB_OK);
wsprintf(sz,TEXT("GXTER:%d"), g_nResult);
MessageBox(NULL,sz,TEXT("GXTER"),MB_OK);
return 0;
}
//------------------------the end--------------------然后把mydll.dll和install.exe放在一起就可以,運行install.exe就可以看到調用DLL的函數的效果。
順便說一下隱式加載DLL的默認路徑
1) 包含可執行映像文件的目錄。
2) 進程的當前目錄。
3) Wi n d o w s系統目錄。
4) Wi n d o w s目錄。
5) PAT H環境變量中列出的各個目錄。
下面先來看看顯式的加載DLL。
(需要如下兩個文件in.exe和dl.dll)
建立一個名為dl的DLL工程,然后新建dl.cpp文件代碼如下:
//
//dl.cpp
//
#include <windows.h>
#include <stdio.h>
int my_fun();
BOOL WINAPI DllMain(HINSTANCE histdll, //
DWORD fdw, //系統調用/卸載時傳遞的消息
PVOID fim) //傳進DLLMAIN內的參數
{
switch(fdw)
{
case DLL_PROCESS_ATTACH: //當系統加載一個這個DLL文件時就會給出這消息
my_fun(); //然后會執行my_fun()函數
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return 1; //發現的一個問題就,這個返回值一定要為1,不能為0。
//不然就會出現一個問題,DLL被加載,但LoadLibrary(dll_path);
//這個函數會返回NULL。錯誤代碼為1114(系統加載DLL文件失敗)。
}
int my_fun()
{
printf("這里填加功能函數代碼!");
return 0;
}
//------------------------the end------------------------------新建一個名為“in”控制臺工程,然后建立一個 in.cpp
//
//in.cpp
//
#include <windows.h>
#include <stdio.h>
int main()
{
int error;
char exe_path[512] ="\0";
HINSTANCE hdll_lib;
char * dll_path ="dl.dll"; //dll文件的路徑 
//加載一個DLL
hdll_lib = LoadLibrary(dll_path);
if(hdll_lib == NULL)
{
error = GetLastError();
printf("error = %d",error);
}
//獲得正在運行的程序的路徑 + 文件名,前提是獲得了這個程序的句柄
GetModuleFileName(hdll_lib,exe_path,sizeof(exe_path));
printf("\n%s\n",exe_path);
//顯式的加載一個DLL的輸出符號。
//GetProcAddress(hdll_lib , "my_fun");
//判斷是否加載了某個DLL
hdll_lib = GetModuleHandle(dll_path);
if(hdll_lib == NULL)
{
printf("lksjdflkjsf");
hdll_lib = LoadLibrary(dll_path);
}
//卸載一個DLL
FreeLibrary(hdll_lib);
getchar();
return 0;
}
//--------------------------the end-------------------------編譯后得到in.exe文件
然后把得到的in.exe和dl.dll文件放在同一目錄下。運行in.exe就可用看到顯式加載DLL的效果。
本問只涉及到了DLL編程的基礎部分,一些深入的概念都沒有具體的講解. 如有錯誤還請通過E-MAIL告訴我。
以后會講些DLL編程的高級部分。
By Gxter
http://www.safechina.net
Gxter at sogou dot com
參考:
MSDN 2000版
《WINDOWS 核心編程》
posted on 2006-05-08 17:51 楊粼波 閱讀(517) 評論(0) 編輯 收藏 引用 所屬分類: 文章收藏




