原地址:http://baixiaozhe.iteye.com/blog/1132025
生成、使用DLL看起來簡單,但做起來才發現還是有一些地方需要注意的。
1. 打開VS2008,新建一個VC工程,選擇Win32類型,Win32項目:
2. 應用程序類型選擇DLL,附加選項選擇到處符號,公共頭文件不要選擇,然後點完成即可。
3. 工程生成後需要修改屬性,在配置屬性的常規選項中將MFC的使用修改爲“靜態庫中使用MFC”。
注意,這一步是必須的,否則寫出來的DLL將需要在有VC2008的環境上才能運行。
4. 關注自動生成的文件MyDllTest.cpp,其中有幾個實例,可以將他們刪除,也可以不管他們。
5. 添加自己的接口,如:GetMyDllVersion
- // 得到當前DLL的版本號
- MYDLLTEST_API UINT32 GetMyDllVerion( VOID )
- {
- return 1234;
- }
6. 在頭文件MyDllTest.h中添加聲明
- MYDLLTEST_API UINT32 GetMyDllVerion( VOID );
7. 添加導出符號定義文件,理論上是可以不要導出定義的,但是那樣的結果就是生成的DLL中的符號名字不明確,只有定義了導出符號,纔可以使得DLL中的藉口函數名稱得以確定。(關於def與dll 請參閱msdn )
- LIBRARY "MyDllTest"
- EXPORTS
- GetMyDllVerion
8. 在項目屬性中設置模塊定義文件爲剛纔建立的symexport.def文件:
9. 生成,可以得到一個MyDllTest.dll,使用Depends工具(VC6.0自帶)可以查看這個DLL中包含了多少接口以及接口名:
會發現除了我們定義的藉口GetMyDllVersion外還有幾個??開頭的接口,他們就是那些沒有在模塊定義文件中定義的藉口自動生成的。
10. 除了DLL外我們還會發現生成了MyDllTest.lib文件,這個lib文件可以在其他的程序使用這個DLL的時候將其連接進去,同時只要包含MyDllTest.h即可調用這個DLL中的藉口了。
如何引入dll
方法一.裝載期間動態加載。(需要lib和dll)
1。新建Win32應用程序空項目。
2。把生成的dll、lib這2個文件複製到新建的目錄下。
3。添加導入庫:工具--項目和解決方案(vs裏是options)--VC++目錄,選擇右側“顯示以下內容的目錄”下的“庫文件”,把lib所在目錄添加。
4。頭文件: MyDllTest.h(與編寫DLL中一樣)
5。源文件:main.c
可註釋#pragma comment(lib," MyDllTest.lib")這條,但必須設置鏈接庫,方法:
右擊項目--屬性--配置屬性--鏈接器--輸入--附加依賴項: MyDllTest.lib
-
#include " MyDllTest.h"
- #include " windows.h"
- #pragma comment(lib," MyDllTest.lib")
- int WINAPI WinMain(__in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd )
- {
- GetMyDllVersion();
- return 0;
- }
方法二:運行期間動態加載。(只需Dll文件即可)
需要使用 Windows API 函數: LoadLibrary 、 GetProcAddress 以及 FreeLibrary
#include <iostream>
#include <windows.h>
using namespace std;
//定義FunctionFunc爲指向一個返回值爲int型 無參數的函數的指針
typedef int (*FunctionFunc)();
int main()
{
FunctionFunc _FunctionFunc;
//加載目標Dll
HMODULE hModule = ::LoadLibrary (TEXT("D:\MyDllTest.dll"));
if (hModule==NULL)//如果Dll加載失敗,釋放它佔用的資源
{
::FreeLibrary(hModule);
}
//取得目標Dll中導出函數的地址(提醒:函數名就是函數的入口地址)
_FunctionFunc=(FunctionFunc)::GetProcAddress (hModule,"GetMyDllVersion");
if (_FunctionFunc==NULL)
{
::FreeLibrary (hModule);
}
int a =_FunctionFunc();
cout<< a<<endl;
::FreeLibrary(hModule);
cin.get();
return 1;
}
有時候我們拿到的是別人的DLL和頭文件,但是卻沒有LIB文件,這時就要使用另外的方法調用DLL中的接口了,例如MD5接口的使用:
- // 按照MSDN中的說明定義函數原型如下
- typedef struct
- {
- ULONG i[2];
- ULONG buf[4];
- unsigned char in[64];
- unsigned char digest[16];
- } MD5_CTX;
- typedef void (CALLBACK* MD5Init_Tpye)(MD5_CTX* context);
- typedef void (CALLBACK* MD5Update_Tpye)(MD5_CTX* context,
- unsigned char * input,
- unsigned int inlen);
- typedef void (CALLBACK* MD5Final_Tpye)(MD5_CTX* context);
- // 使用MD5接口
- HINSTANCE hDLL;
- // MD5接口是在Cryptdll.dll中的
- hDLL = LoadLibrary(TEXT("Cryptdll.dll" ));
- MD5Init_Tpye MD5Init;
- MD5Update_Tpye MD5Update;
- MD5Final_Tpye MD5Final;
- // 得到接口指針
- MD5Init = (MD5Init_Tpye)GetProcAddress(hDLL, "MD5Init" );
- MD5Update = (MD5Update_Tpye)GetProcAddress(hDLL, "MD5Update" );
- MD5Final = (MD5Final_Tpye)GetProcAddress(hDLL, "MD5Final" );
- if (!MD5Init || !MD5Update || !MD5Final)
- {
- // 取得接口指針失敗
- FreeLibrary(hDLL);
- return ;
- }
- MD5_CTX md5_context;
- MD5Init(&md5_context);
- MD5Update(&md5_context, src, length);
- MD5Final(&md5_context);
- // 不要忘記釋放導入的DLL
- FreeLibrary(hDLL);
這就是目前我知道的兩種使用DLL的方法了,至於還有沒有其他的方法,暫時沒有這方面的需求,也就不去花腦力想了。。。