精華區beta C_and_CPP 關於我們 聯絡資訊
大家好 今天在試著寫簡單的DLL看怎麼用 目前我是用vc8 開 console專案 Application type選dll 勾選export symbols 然後就開始試著玩看看 產生了.lib .dll和 原來的.h 想問各位 我寫.h檔案 是不是一定要使用 #ifdef __cplusplus extern "C" { 把宣告的函式包起來 在另一個讀dll的程式利用 HMODULE hGAL=LoadLibrary("xxx.dll") GetProcAddress(hGAL,"function_name") <=======這函式讀取某function 問題1 之前卡在一直都無法讀到這函式 原來是沒加上extern"C" 所以C++ compiler會對function name做手腳 導致找不到這function 所以寫dll一定要使用extern"C"來包嗎?? 如果不用extern"C"包 就一定要附上.lib, 不要用GetProcAddress來找函式 以上是我測試所得到的心得但是不知道是不是真的這樣子@@ 問題2 如果dll裡面有寫class 是不是就一定要附上 .lib 才可以利用這class產生instance 有沒有類似問題一的函式可以讀取class嗎??(我想說是不是可以不用給.lib) 因為我同事說他沒給lib也可以new一個class的instance 讓我覺得很怪異.. 我卻一直出現無法解析的外部符號 需要附上lib才可以..... 問題3 我以為作dll就不會產生lib檔案 之前編譯靜態lib 就想成 把cpp轉換成lib 其實lib就是cpp~~ 但是今天做dll 原來會產生.lib檔案 請教各位這lib檔案是紀錄什麼資訊 明明定義的資訊都跑到dll了為什麼還需要lib檔案呢 以上問題有點煩雜 想釐清觀念 謝謝各位~ ps. 另外有看到某個前輩code 有使用interface這關鍵字 行為很像class 這也是跟做DLL有關嗎= = thx -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 122.147.15.66 ※ 編輯: QQ29 來自: 122.147.15.66 (12/24 19:35) ※ 編輯: QQ29 來自: 122.147.15.66 (12/24 20:10) ※ 編輯: QQ29 來自: 122.147.15.66 (12/24 20:12) > -------------------------------------------------------------------------- < 作者: aecho (星空下的鮪魚) 看板: C_and_CPP 標題: Re: [問題] 使用 & 製作 dll的問題 時間: Thu Dec 24 21:27:42 2009 刪光光… 給你前一陣子在看的文件… 我後來覺得要了解.dll在幹麻 有兩個連結可以看一下。 function pointer http://www.newty.de/fpt/index.html Regular DLL Tutor For Beginners http://www.codeproject.com/KB/DLL/RegDLL.aspx 心得: 我認為GetProcAddress()就是為了拿到函式指標, 而為了拿到正確的函式指標,就需要給他足夠的資訊去找到那個函式的位址。 目前看過的GetProcAddress()的參數有兩種, 一種是.dll裡面的名字;一種是個數字,如GetProcAddress(1)。 會用到GetProcAddress()和LoadLibrary()的話, 就只需要.dll,不需要.lib和.h了。 -- <. . 野ブタパワー ~~~ @@ 注入!! ︱﹨ -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 59.115.243.17
aecho:好像沒回答到問題 = w = 12/24 21:31
ledia:.h 還是要吧, 不然你怎麼知道 fp 的 prototype ? 12/24 22:26
sunneo:對啊 除非是(X.bin)--->Y.dll 其中Y.dll不公開 12/25 00:09
> -------------------------------------------------------------------------- < 作者: aecho (星空下的鮪魚) 看板: C_and_CPP 標題: Re: [問題] 使用 & 製作 dll的問題 時間: Fri Dec 25 07:46:21 2009 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 59.115.243.17
aecho:好像沒回答到問題 = w = 12/24 21:31
ledia:.h 還是要吧, 不然你怎麼知道 fp 的 prototype ? 12/24 22:26
sunneo:對啊 除非是(X.bin)--->Y.dll 其中Y.dll不公開 12/25 00:09
fp的ptorotype的話,就看文件了,或是和對方約定好prototype。 像手頭上的一個project,就是約定好prototype,而有.h也沒有用。 匯出到.dll的function,.h裡沒有宣告。都只寫在.cpp裡面。 因為原本就設計成需要用動態連結的方式。 -- 或許人生是一段整合內在的自己 並尋求人間一點真情的過程吧 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 59.115.243.17
ledia:你還是需要 FP 的 type, 不然要怎麼接呢? 這些他沒給 .h 12/25 09:23
ledia:還是得自己定義吧, 是一樣的意思 12/25 09:23
aecho:我覺得需要.h和知道FP的type,是兩件事。 12/25 09:42
aecho:知道FP的type,會對GetProcAddress()再轉型成應有的type。 12/25 09:43
aecho:而有.h,是直接使用.h裡的定義了~~ 12/25 09:44
aecho:如果當成一般的pointer來看,GetProcAddress()就像是回傳了 12/25 09:46
aecho:void * 這一種pointer回來,而要用的時候再轉型成正確的type 12/25 09:46
VictorTom:看起來是兩件事, 其實在這個地方它的用途是一樣的, 12/25 09:53
VictorTom:終究你需要知道Func / FP的type, 你get回來才能轉型, 12/25 09:54
VictorTom:放.h跟私下溝通好prototype, 意義上其實也滿像了吧@_@" 12/25 09:55
ledia:嗯, 問題在於, 再轉形成正確的 type, 這個 type 是什麼? 12/25 10:45
ledia:如果你不是從他的 .h 拿, 你也要從手冊裡整理出來弄成很像 12/25 10:46
ledia:有一個 .h 裡面定義一堆 prototype 一樣的形式吧 12/25 10:46
ledia:這明明就是同一件事呀 XD 12/25 10:46
ledia:事實上從手冊裡整理出來是很不好的 coding style 12/25 10:47
ledia:今天換一個版本竟然要動到你的 code ?! 這不是很奇怪嗎? 12/25 10:47
ledia:要也是置換他給的 header file 就好啦 12/25 10:49
aecho:嗯,我想應該是用法有些不一樣吧~~ 12/25 12:33
aecho:因為我這邊在用的,轉出的dll,還是要包一個class出來, 12/25 12:33
aecho:這個class一開始會LoadLibrary,並且取得需要的FP, 12/25 12:34
aecho:不用的時候就FreeLibrary了。 12/25 12:34
aecho:而dll的作者和該class的作者通常是同一個吧 XDD 12/25 12:35
> -------------------------------------------------------------------------- < 作者: aecho (星空下的鮪魚) 看板: C_and_CPP 標題: Re: [問題] 使用 & 製作 dll的問題 時間: Fri Dec 25 13:04:35 2009
ledia:你還是需要 FP 的 type, 不然要怎麼接呢? 這些他沒給 .h 12/25 09:23
ledia:還是得自己定義吧, 是一樣的意思 12/25 09:23
aecho:我覺得需要.h和知道FP的type,是兩件事。 12/25 09:42
aecho:知道FP的type,會對GetProcAddress()再轉型成應有的type。 12/25 09:43
aecho:而有.h,是直接使用.h裡的定義了~~ 12/25 09:44
aecho:如果當成一般的pointer來看,GetProcAddress()就像是回傳了 12/25 09:46
aecho:void * 這一種pointer回來,而要用的時候再轉型成正確的type 12/25 09:46
VictorTom:看起來是兩件事, 其實在這個地方它的用途是一樣的, 12/25 09:53
VictorTom:終究你需要知道Func / FP的type, 你get回來才能轉型, 12/25 09:54
VictorTom:放.h跟私下溝通好prototype, 意義上其實也滿像了吧@_@" 12/25 09:55
ledia:嗯, 問題在於, 再轉形成正確的 type, 這個 type 是什麼? 12/25 10:45
ledia:如果你不是從他的 .h 拿, 你也要從手冊裡整理出來弄成很像 12/25 10:46
ledia:有一個 .h 裡面定義一堆 prototype 一樣的形式吧 12/25 10:46
ledia:這明明就是同一件事呀 XD 12/25 10:46
ledia:事實上從手冊裡整理出來是很不好的 coding style 12/25 10:47
ledia:今天換一個版本竟然要動到你的 code ?! 這不是很奇怪嗎? 12/25 10:47
ledia:要也是置換他給的 header file 就好啦 12/25 10:49
aecho:嗯,我想應該是用法有些不一樣吧~~ 12/25 12:33
aecho:因為我這邊在用的,轉出的dll,還是要包一個class出來, 12/25 12:33
aecho:這個class一開始會LoadLibrary,並且取得需要的FP, 12/25 12:34
aecho:不用的時候就FreeLibrary了。 12/25 12:34
aecho:而dll的作者和該class的作者通常是同一個吧 XDD 12/25 12:35
好像是第一次可以回同一個系列回那麼多次... = w = 而且一直繞著 h的話題~~ 我先整理一下好了,dll分靜態和動態連結兩種。 靜態需要.h, .lib 和.dll,而動態需要 .h, .dll好了。 上面所討論的.h.h是不一樣的東西了… = w = .h是裡面定義了FP的type,也就是像 typedef void (WINAPI *ptrFuncFoo)(); 這類的function pointer的type宣告。 而像.h則是長的像這個模樣的…配合.lib, .dll使用 #ifdef ExportDll #define ExportDll __declspec( dllexport ) #else #define ExportDll __declspec( dllimport ) #endif void ExportDll WINAPI foo(); -- 有多少笑語 就有多少哭泣 幸福的背後 總是隱藏著悲劇 -----摘自 趙寧 --找一個字代替-- -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 59.120.59.242
Bencrie:其實應該叫implicit跟explicit link,兩個都是dynamic 12/25 13:28
Bencrie:linking。static link應該是說object archives那種。 12/25 13:29
QQ29:看了一下請問大家所說的fp是什麼東西呢@@ 12/25 14:24
twotwoone:函數指標 12/25 14:29
aecho:Orz 受教了~~ 12/25 16:33
sunneo:H的話題 (誤 12/25 23:19
> -------------------------------------------------------------------------- < 作者: legnaleurc (CA) 看板: C_and_CPP 標題: Re: [問題] 使用 & 製作 dll的問題 時間: Fri Dec 25 15:28:43 2009 ※ 引述《QQ29 (我愛阿蓉)》之銘言: : 大家好 今天在試著寫簡單的DLL看怎麼用 : 目前我是用vc8 開 console專案 Application type選dll 勾選export symbols : 然後就開始試著玩看看 : 產生了.lib .dll和 原來的.h : 想問各位 : 我寫.h檔案 是不是一定要使用 : #ifdef __cplusplus : extern "C" { : 把宣告的函式包起來 : 在另一個讀dll的程式利用 : HMODULE hGAL=LoadLibrary("xxx.dll") : GetProcAddress(hGAL,"function_name") <=======這函式讀取某function : 問題1 : 之前卡在一直都無法讀到這函式 原來是沒加上extern"C" : 所以C++ compiler會對function name做手腳 導致找不到這function : 所以寫dll一定要使用extern"C"來包嗎?? : 如果不用extern"C"包 就一定要附上.lib, 不要用GetProcAddress來找函式 : 以上是我測試所得到的心得但是不知道是不是真的這樣子@@ 好像是 ... 兩回事(吧?) 之所以要 extern "C" 應該是因為 GetProcAddress 是 C 的函式 所以在 C++ 的 name mangling 上要加上 extern "C" 才找得到 __declspec(dllexport) 出來的 .lib 是給那些"在編譯期就需要 symbol"用的 : 問題2 : 如果dll裡面有寫class : 是不是就一定要附上 .lib 才可以利用這class產生instance : 有沒有類似問題一的函式可以讀取class嗎??(我想說是不是可以不用給.lib) : 因為我同事說他沒給lib也可以new一個class的instance 讓我覺得很怪異.. : 我卻一直出現無法解析的外部符號 需要附上lib才可以..... 通常的作法是另外宣告一個函式: extern "C" YourClass * createYourClass(); 然後就可以用 dlsym 或是 GetProcAddress 拿到這個函式 再用它來生成 instance,這樣你不需要 explicit export dll : 問題3 : 我以為作dll就不會產生lib檔案 : 之前編譯靜態lib 就想成 把cpp轉換成lib 其實lib就是cpp~~ : 但是今天做dll 原來會產生.lib檔案 : 請教各位這lib檔案是紀錄什麼資訊 : 明明定義的資訊都跑到dll了為什麼還需要lib檔案呢 : 以上問題有點煩雜 想釐清觀念 : 謝謝各位~ 我的理解是,如果你在編譯期就要用到 dll 的 symbol 比方說你繼承某 class 或是不經由 dlsym 就要用 dll 裡的函式 就要 explicit export dll (好像只有 Windows 搞這套?) 這種的特徵是程式執行前就要載入 dll,否則不能執行 如果你是執行期才會用到該 dll 的內容,就不需要 export 比方說 plugin 或是其他和主要介面無關的 lib 這種通常是程式執行到一半才會載入,也可以中途卸載 : ps. 另外有看到某個前輩code 有使用interface這關鍵字 行為很像class : 這也是跟做DLL有關嗎= = thx sorry, 才疏學淺,沒看過 orz -- 自High筆記(半荒廢) http://legnaleurc.blogspot.com/ -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 123.205.248.119 > -------------------------------------------------------------------------- < 作者: firose (guest也是也是也是也是也) 站內: C_and_CPP 標題: Re: [問題] 使用 & 製作 dll的問題 時間: Sat Dec 26 00:43:10 2009 ※ 引述《QQ29 (我愛阿蓉)》之銘言: : 大家好 今天在試著寫簡單的DLL看怎麼用 : 目前我是用vc8 開 console專案 Application type選dll 勾選export symbols : 然後就開始試著玩看看 : 產生了.lib .dll和 原來的.h : ... : 略 ; ... : 問題3 : 我以為作dll就不會產生lib檔案 : 之前編譯靜態lib 就想成 把cpp轉換成lib 其實lib就是cpp~~ : 但是今天做dll 原來會產生.lib檔案 : 請教各位這lib檔案是紀錄什麼資訊 : 明明定義的資訊都跑到dll了為什麼還需要lib檔案呢 : 以上問題有點煩雜 想釐清觀念 : 謝謝各位~ : ps. 另外有看到某個前輩code 有使用interface這關鍵字 行為很像class : 這也是跟做DLL有關嗎= = thx 之前看書記得是這樣: 對於 dll 的函式呼叫, 如果你是用隱式連結, 就需要 .h 跟 .lib 標頭檔只是讓它引用外部符號, 產生目的檔, 但是函式實體 compiler 根本找不到 到連結的時候, linker 還是找不到函式實體, 所以它應該會判定它是在外部模組中 那它就要做記號啦, 說這是一個待修正的項目, 所以 loader 會填入正確的函式位址 這裡的問題是它如何找到那個函式位址? 它可以把每一個函式呼叫點都作上記號 然後 loader 就一項一項地去修正, 但是這樣很沒效率, 會浪費程式載入的時間 所以有一個東西叫 IAT (Import Address Table) 所有函式呼叫會被翻譯成間接 取值, 然後載入器只要修正輸入表的項目, 就可以讓所有的函式呼叫都正常工作 它的差別是在, 若程式對某函式多次呼叫, 用輸入表的方式可以只修改一個地方 然後對 VC 來說, 那個 .h 裡面的函式有兩種: 有/無 dllimport 沒有寫 dllimport 的東西, 編譯器不能直接假設它是 dll 的函式 所以它會先假設一個位址, 把函式呼叫跳到那個地方, 然後連結器 會最終會了解到那是個 dll 的函式, 並且在 .lib 找到這樣的東西 jmp DWORD PTR [XXXX] 那個 XXXX 就是 IAT 項目位址, 那個位址上的值 會在程式載入的時候被修正, 這樣程式就可以正常進行, 這裡我猜 .lib 當然也會存放著某個函式的 symbol 是位在哪個 dll, 並把相關引用資訊 填入 PE 檔裡, 讓載入器可以知道要載入哪個 dll 並用它的真實位址修正 AIT 中的位址值. 另一種就是有寫 dllimport 的函式, 好像是在 VC 2.0 以後支援的, 它會把函式呼叫直接翻成 call DWORD PTR[XXXX] 這樣就可以 省下一個 call 的跳躍, 理論上會比較有效率一點, 那這時 .lib 應該 仍然要存相關的 dll 跟函式的 symbol 只是沒有那個 jump stub (不然載入器怎麼知道要載入什麼 dll ? 我們又沒有告訴它) 另外 BCB 書上是說 linker 會自動填上 jmp DWORD PTR[XXXX] 而不是 存在 .lib 之中 記憶中的樣子是這些, 有說錯請大大們指教 @@ -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 114.25.154.218 > -------------------------------------------------------------------------- < 作者: mellean (莉莉姆) 看板: C_and_CPP 標題: Re: [問題] 使用 & 製作 dll的問題 時間: Sun Dec 27 13:46:49 2009 ※ 引述《legnaleurc (CA)》之銘言: : ※ 引述《QQ29 (我愛阿蓉)》之銘言: : : 大家好 今天在試著寫簡單的DLL看怎麼用 : : 目前我是用vc8 開 console專案 Application type選dll 勾選export symbols : : 然後就開始試著玩看看 : : 產生了.lib .dll和 原來的.h : : 想問各位 : : 我寫.h檔案 是不是一定要使用 : : #ifdef __cplusplus : : extern "C" { : : 把宣告的函式包起來 : : 在另一個讀dll的程式利用 : : HMODULE hGAL=LoadLibrary("xxx.dll") : : GetProcAddress(hGAL,"function_name") <=======這函式讀取某function : : 問題1 : : 之前卡在一直都無法讀到這函式 原來是沒加上extern"C" : : 所以C++ compiler會對function name做手腳 導致找不到這function : : 所以寫dll一定要使用extern"C"來包嗎?? : : 如果不用extern"C"包 就一定要附上.lib, 不要用GetProcAddress來找函式 : : 以上是我測試所得到的心得但是不知道是不是真的這樣子@@ : 好像是 ... 兩回事(吧?) : 之所以要 extern "C" 應該是因為 GetProcAddress 是 C 的函式 : 所以在 C++ 的 name mangling 上要加上 extern "C" 才找得到 這邊應該不太對 並不是因為GetProcAddress是C的函式,所以要用extern "C"才找得到 不使用extern "C"來宣告你要export的函式,GetProcAddress還是找的到的 這跟compiler為這個函式產生的名稱和你帶入GetProcAddress要找的名稱是否相符有關 在C++裡只有為函式指定c linkage時函式名稱才會以C的方式來紀錄 這樣我們才能只帶入單純函式名稱就找得到函式,否則我們要帶入C++的函式名稱來找 假設我們在dll有個function 定義成 bool Foo(const char*, int); 那使用GetProcAddress時可能要寫成這樣 GetProcAddress(hModule, "?Foo@@YG_NPBDH@Z");來取得 定義成 extern "C" bool Foo(const char*, int); 才能用GetProcAddress(hModule, "Foo");來取得 問題就在我們要知道C++為函式產生的名稱是比較麻煩的 所以用C的方式比較簡單 : : ps. 另外有看到某個前輩code 有使用interface這關鍵字 行為很像class : : 這也是跟做DLL有關嗎= = thx : sorry, 才疏學淺,沒看過 orz 這個應該屬於COM在用的東西,寫IDL檔時宣告介面所用的關鍵字 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 122.116.37.95