主題:
[問題] dll 檔的使用跟製造問題~
[打印本頁]
發表人:
Daidouji
時間:
2003-10-6 11:24 PM
主題:
[問題] dll 檔的使用跟製造問題~
如果說我想把一個我的 class 做成 dll 檔~
借給同學們使用~
請問我應該怎麼寫才可以讓他 "export" <--- ?
又~
我要怎麼在我的程式裡面呼叫這個 dll 然後使用它~
謝謝大家~
發表人:
AQUA
時間:
2005-2-28 01:53 PM
據我所知有兩種方法..
第一種lib的載入法(static),因為如果是你直接產生的DLL (會有X.lib X.def X.dll)
然後在def 上宣告 export table 的 function
之後在欲使用該DLL的client 端上 直接載入該lib就可以了(#pragma comment() )
第二種是動態載入法(dynamic)
欲使用該DLL的client,就直接用loadlibrary的方式,載入該dll,再
用GetProcAddress去連結該function address
example:
typedef UINT (CALLBACK* LPFNDLLFUNC1)(DWORD,UINT);
HINSTANCE hDLL; // Handle to DLL
LPFNDLLFUNC1 lpfnDllFunc1; // Function pointer
DWORD dwParam1;
UINT uParam2, uReturnVal;
hDLL = LoadLibrary("MyDLL");
if (hDLL != NULL) {
lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL,
"DLLFunc1");
if (!lpfnDllFunc1) { // handle the error
FreeLibrary(hDLL);
return SOME_ERROR_CODE;
} else { // call the function
uReturnVal = lpfnDllFunc1(dwParam1, uParam2);
}
}
當然這兩種實際的範例我還要找一下,如果有錯,還請其他的高人指導指導
不好意思,現醜了..
[AQUA 在 2005-2-28 02:12 PM 作了最後編輯]
發表人:
swimman
時間:
2005-3-12 03:20 AM
class 做成DLL也就是俗稱的COM
如果你用的是VB那還挺簡單的
如果不是那可能就是個long way to go
Aqua兄講的是含式庫類的DLL
那種通常都用純C開發的並沒有CLASS
發表人:
AQUA
時間:
2005-3-15 05:14 PM
轉貼自Eastshare的 Jing
因為內容較長,所以重新發一文,沒有灌水的意思唷...
======================================================
下面要介紹的是 DLL 與 lib 之間的關係, 我們會討論到 如何建立 DLL 檔,如何使用 DLL檔,
另外,我們也會討論到如何使用 LoadLibrary 動態的載入 dll.
希望有興趣的人可以試試看.
(在這裡我們討論主題與 C++ 程式設計有關,所以如果你不熟悉這個語言,你可能會有點吃力)
好了, 我們就開始吧
如果你寫了一堆 functions 且放在不同的 file 中, 你可以把他們全部放到一個 library 檔案中.
這樣可以方便管理以及方便散佈與增加鏈結的效率.
我們都知道要產生一個可執行的檔案你需要兩個階段的工作:
1. Compiler 幫我們建立 Object 檔
2. Linker 進行連結部分,幫我們把 Object 檔參考到的 symbol 連結起來
Linker 接受兩種標準的 COEF 格式的 library 檔[1]
(1) standard libraries: 包含 一堆 object 檔的集合
(2) import libraries: 包含另一個程式所 export 出來的 symbol 資訊
其中 import library 是建立 DLL 檔時, Linker 產生出 import library 來描述 export symbol 的訊息.
上面這兩種格式的附檔名都是 .lib
兩者間的差別在於: standard library 包含了所有的資料, 相對於 import library 則只有包含 export symbol 的link相關資料,完整資料放在另一個檔案 DLL 中.
看到這裡有點累, 別擔心, 最後會有例子把全部串起來 :rolleyes:
如果你用靜態鏈結的方式建立你的執行檔, 那麼你就必須指定 .lib 使得 linker 可以在鏈結階段連結你的 library 資訊.
在這裡有個選項:
如果你鏈結的檔案是 standard libraries, 那麼一切都沒事,產生出來的執行檔可以帶到各處執行都沒問題
如果你鏈結的檔案是 import libraries, 那麼你散佈的執行檔只包含部分資訊,
你還需要順便散佈 .dll 檔,而且要放在可搜尋到的位置,
這樣執行檔才可以順利執行.
其中, DLL 檔就是所謂的 Dynamic link libraries 的縮寫. 使用 DLL + import library 可以讓你的執行檔
只包含必要的部分, 其他共用的部分可以放在 DLL 檔讓其他程式共享. 這使得你的執行檔可以佔比較小的空間,
而且若 DLL 檔已經被其他 process 載入時,你的執行檔就不用載入該共享的 DLL 檔而使用 map 的方式,
將 DLL 檔的 code map 到你process 的 virtual space 中, 進而節省 Loading 的時間使得開啟你的程式.
會有比較快的反應時間.
更進一步的來說,你還可以使用 LoadLibarary 指令,讓你要用到某個 .DLL export 的symbol的時候, 才 map 該 DLL
, 不用的時候使用 FreeLibary 指令 unmap DLL, 使你更精確的控制你 process 所使用的空間. 順便提一下
在 linux(或 UNIX) 世界也有 DLL, 只是他的附檔名通常被稱為 .so.
那麼要如何建立 DLL 與使用 DLL ?
基本上, 我們可以在 source code 加上下面的敘述將一個程式的 symbol export 出去[2]:
__declspec(dllexport)
如果你使用 implicit link 使用你的 DLL, 那麼你的程式很簡單的可以直接使用 DLL export 出來的symbol
. 例如 直接呼叫 DLL export 出來的 function Add.
但是在這裡有一個問題, 那就是你的source code 中直接使用 Add 這個 symbol, C++ 會告訴我們
------------------------------------------------
error LNK2019: unresolved external symbol 的錯誤
------------------------------------------------
這是因為 linker 不知道 你使用的 Add 是放在其他的程式檔(某個DLL)中, 所以才會產生這個錯誤.
在這裡,你應該在 project 中或 source code 中指出"Add"這個 symbol 的詳細資訊, 才會正確連結成功.
而這個資訊就放在 .lib 檔中.
在 source code 指定 .lib 的範例
--------------------------------------------------------------------------------------------
#pragma comment( lib, "C:\\Documents and Settings\\jing\\桌面\\MyDLL\\DEBUG\\MyDLL.lib" ) --------------------------------------------------------------------------------------------
結合上面的說法:
寫個範例給大家看看:
Step 1: 先用 整合式開發環境(VC) 建立一個 DLL 專案
Step 2: 寫 header file
--------------MyLib.h---------------
// 宣告要 export 的 function 以及全區域變數
// 這個檔案要include任何想要使用 DLL 中function 的 executable file 中
#ifdef MYLIBExport
#define MYLIBAPI extern "C" __declspec(dllexport) // 說明我要 export
#else
#define MYLIBAPI extern "C" __declspec(dllimport) // 說明我要 import
#endif
MYLIBAPI int Add(int nLeft, int nRight);
----------------------------------------
Step 3: 寫 cpp 檔
------------- MyLib.cpp---------------------
#include
#define MYLIBExport // 表示這個 .cpp 檔要 export symbol
#include "MyLib.h"
MYLIBAPI int Add(int nLeft, int nRight) {
g_nResult = nLeft + nRight;
return(g_nResult);
} -----------------------------------------
Step 4: 編譯與鏈結: VC 就會在 的專案目錄下的 Debug 建立 .lib 檔與 .dll 檔
使用 DLL 檔的部分
如果你使用的是 implicit link 你的 DLL, 那麼前面說過,你需要 .lib 幫忙產生執行檔.
範例如下:
Step 1: 利用 VC 建立新的專案: UseDLL
Step 2: 指定 DLL 的 .h 檔位置,把他 include 進來.
#include "C:\\Documents and Settings\\jing\\桌面\\MyDLL\\MyLib.h" Step 3: 加入 lib 檔到你的 source code
#pragma comment( lib, "C:\\Documents and Settings\\jing\\桌面\\MyDLL\\DEBUG\\MyDLL.lib" ) Step 4: 編譯執行(大功告成)
所以你的程式應該長的像這樣:
-----------------------------------
#include "C:\\Documents and Settings\\jing\\桌面\\MyDLL\\MyLib.h"
#pragma comment( lib, "C:\\Documents and Settings\\jing\\桌面\\MyDLL\\DEBUG\\MyDLL.lib" )
int _tmain(int argc, _TCHAR* argv[]){
int c=Add(1,2); // << -- 直接使用 export 的function
return 0;
}
---------------------------------------
若你使用的是 explicit link 方式使用你的 DLL, 那麼你的 source 就不能直接使用 DLL export
出來的 symbol了, 情況是你必須寫程式自己載入 DLL 檔,接著利用取出你要的存取的 fucntion 所在的
位址, 然後使用 function pointer 間接的呼叫 function.
所以情況如下:
--------------------------------------------
typedef int (*MYPROC)(int,int);
void main(){
HINSTANCE hinstDll = LoadLibrary("MyDLL"); // Step 1: 將 DLL 載入
MYPROC ProcAdd;
ProcAdd=(MYPROC)GetProcAddress(hinstDll,"Add"); // Step 2: 宣告指標
int data=(ProcAdd)(2,4); // Step 3: 呼叫 function
}
--------------------------------------------
你可以看到, 在這裡完全沒有直接使用 DLL export 出來的 symbol, 我們是利用 Win32 API 幫我們
間接取得 呼叫 function 的 map 位址,然後間接的呼叫. 所以在 linking 階段不需要使用 lib 檔提供
有關 symbol "Add" 的資訊.
所以結論是: .lib 檔描述的是 提供 linker 有關 export symbol 的鏈結資訊.
.dll 檔內容是包含 function 的可 relocated object code,
在其中有一個 export section 紀錄著這個 DLL 所有 exported 的 symbol.
這兩個檔案可能用不同的方式是描述 exported symbol.
你或許會問: 為什麼要分成這兩個檔案呢? 在 implicit link 時就直接使用 .dll 就好了嘛,
.dll 就有 export section 了,直接擷取該節區就有資料何必使用 .lib ?
我的解答是:
透過 .lib 間接描述 .dll export symbol 有好處. 因為一旦 linking 階段完成
靜態鏈結你的source code 與 .lib symbol 也就完成了, 所以當 DLL 檔因為新版本
出現需要改變時,只要直接更換 DLL 檔就可以了不需要換重新編譯執行檔.
延伸讀物: [MSDN 2003 January]
[1]
[2] ms-help://MS.MSDNQTR.2004JAN.1033/vclang/html/_pluslang_The_dllexport_and_dllimport_Attributes.htm
by Jing
========================================================
發表人:
swimman
時間:
2005-3-15 09:26 PM
AQUA兄
DLL有兩種一種是動態連結程式庫(Dynamic Linking Library,DLL)
另一種也就是COM Component Object Model
動態程式庫最有名的就是User32.dll ,KERNEL32.DLL ,GDI32.DLL
這三個是視窗寫作的基礎
不過你要做什麼事都必須透過呼叫這三個DLL來達成
COM則是這十年來微軟最大力推動的東西
所謂元件式的程式開發像是VB所有可以用的控制項都是COM元件
連接資料庫的ADO,全套的OFFICE都是COM
甚至連WORD檔案PDF檔案都是activeX Document也就是COM元件
所以他們不是資料檔而是可載入執行程式,必須要容器載入來執行
所謂的容器就是WORD的執行檔
不過現在微軟已經把COM踢進垃圾桶了
開始改推COM+
這些說起來是很長的故事
我想原來發問的人應該是想用COM啦
不過COM是很複雜的一種技術
外行人用VB玩一玩就好了
歡迎光臨 TWed2k (http://twed2k.org/)
Powered by Discuz! 4.1.0