查看積分策略說明發表回覆
Discuz! 代碼
提示插入
直接插入
說明訊息

插入粗體文本 插入斜體文本 插入下劃線 置中對齊 插入超級連結 插入信件位址 插入圖像 插入 flash 插入代碼 插入引言 插入列表
刪除線 直線分隔線 虛線分隔線
    
添加文字底框
內容 [字數檢查]:

表情符號

更多 Smilies
字型大小 |||
溫馨提示:本區開放遊客瀏覽。


文章關鍵字 : [功能說明]
(關鍵字可加強搜索準確性, 如關鍵字多於一組, 請以 , 作分隔, e.g. : 阿笨,shiuh,第一笨)

 關閉 URL 識別 | html 禁用
 關閉 表情符號 | 表情符號 可用
 關閉 Discuz! 代碼 | Discuz! 代碼 可用
使用個人簽名
接收新回覆信件通知
推薦放檔網絡空間

檔案(Torent, zip等)
  1. freedl
  2. multiupload
  3. btghost
  4. 便當狗
  5. mediafire
  6. pillowangel
圖片(JPG, GIF等)
  1. hotimg
  2. tinypic
  3. mousems2
  4. imageshack
  5. imm.io
>>>歡迎推薦好用空間


最新10篇文章回顧
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玩一玩就好了


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-12 03:20 AM

class 做成DLL也就是俗稱的COM
如果你用的是VB那還挺簡單的
如果不是那可能就是個long way to go
Aqua兄講的是含式庫類的DLL
那種通常都用純C開發的並沒有CLASS


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 作了最後編輯]


Daidouji

 發表於 2003-10-6 11:24 PM

如果說我想把一個我的 class 做成 dll 檔~

借給同學們使用~

請問我應該怎麼寫才可以讓他 "export" &lt;--- ?

又~

我要怎麼在我的程式裡面呼叫這個 dll 然後使用它~

謝謝大家~





所在時區為 GMT+8, 現在時間是 2024-4-27 10:36 PM
清除 Cookies - 連絡我們 - TWed2k © 2001-2046 - 純文字版 - 說明
Discuz! 0.1 | Processed in 0.025046 second(s), 6 queries , Qzip disabled