RSS   



  可打印版本 | 推薦給朋友 | 訂閱主題 | 收藏主題 | 純文字版  


 


 
主題: [問題] dll 檔的使用跟製造問題~   字型大小:||| 
Daidouji
鐵驢友〔初級〕
等級: 4


今日心情

 . 積分: 24
 . 文章: 317
 . 收花: 74 支
 . 送花: 42 支
 . 比例: 0.57
 . 在線: 404 小時
 . 瀏覽: 4080 頁
 . 註冊: 8222
 . 失蹤: 2292
 . 新竹
#1 : 2003-10-6 11:24 PM     只看本作者 引言回覆

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

借給同學們使用~

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

又~

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

謝謝大家~



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  發私人訊息  Blog  快速回覆 新增/修改 爬文標記
AQUA
驢有所悟
等級: 3等級: 3


 . 積分: 13
 . 文章: 62
 . 收花: 54 支
 . 送花: 83 支
 . 比例: 1.54
 . 在線: 300 小時
 . 瀏覽: 800 頁
 . 註冊: 7329
 . 失蹤: 4555
 . 台灣
#2 : 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 作了最後編輯]



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  發私人訊息  Blog  快速回覆 新增/修改 爬文標記
swimman
驢手小試
等級: 2


 . 積分: 8
 . 文章: 63
 . 收花: 55 支
 . 送花: 5 支
 . 比例: 0.09
 . 在線: 956 小時
 . 瀏覽: 80 頁
 . 註冊: 7423
 . 失蹤: 3508
#3 : 2005-3-12 03:20 AM     只看本作者 引言回覆

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



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  發私人訊息  Blog  快速回覆 新增/修改 爬文標記
AQUA
驢有所悟
等級: 3等級: 3


 . 積分: 13
 . 文章: 62
 . 收花: 54 支
 . 送花: 83 支
 . 比例: 1.54
 . 在線: 300 小時
 . 瀏覽: 800 頁
 . 註冊: 7329
 . 失蹤: 4555
 . 台灣
#4 : 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

========================================================



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  發私人訊息  Blog  快速回覆 新增/修改 爬文標記
swimman
驢手小試
等級: 2


 . 積分: 8
 . 文章: 63
 . 收花: 55 支
 . 送花: 5 支
 . 比例: 0.09
 . 在線: 956 小時
 . 瀏覽: 80 頁
 . 註冊: 7423
 . 失蹤: 3508
#5 : 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玩一玩就好了



[如果你喜歡本文章,就按本文章之鮮花~送花給作者吧,你的支持就是別人的動力來源]
本文連接  
檢閱個人資料  發私人訊息  Blog  快速回覆 新增/修改 爬文標記

   

快速回覆
表情符號

更多 Smilies

字型大小 : |||      [完成後可按 Ctrl+Enter 發佈]        

溫馨提示:本區開放遊客瀏覽。
選項:
關閉 URL 識別    關閉 表情符號    關閉 Discuz! 代碼    使用個人簽名    接收新回覆信件通知
發表時自動複製內容   [立即複製] (IE only)


 



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