[教學] 製作 DLL 的簡易方法

看板EzHotKey作者 (蹲在人面獅身像裡)時間16年前 (2008/12/07 06:31), 編輯推噓2(200)
留言2則, 2人參與, 最新討論串1/1
嗯,看標題就覺得和版旨有點不符... 不過一來這是版主大人提的問題,所以應該不會被水桶 二來不管 AutoIt 或 AutoHotKey 都用的上類似的知識 尤其 DLL 配合 AutoIt 的 MemoryDll UDF 又特別的好用(又再賣瓜了) 所以還是簡單寫個教學好了 首先,需要的東西有: 1. 原始碼(去找現成的或是自己寫),這裡用一個簡單的 crc32 做範例 2. 可將原始碼 compile 成 .obj 的 compiler 以下範列用的是 Dev-C++ with Mingw/GCC 3.4.2 3. Microsoft 的 linker,檔名 link.exe,版本不要太新 找不到的人去 http://www.masm32.com/masmdl.htm 下載 MASM32 用 WinRAR 或 7-Zip 開啟 install.exe,解出 link.exe 和 mspdb50.dll 即可 為什麼不用其它的 linker 呢?因為目前只有 MS 的 linker 吃 COFF 也吃 OMF 不過只限於舊版,新版的反而只吃 COFF 了,真是越做越退步 注: OMF 和 COFF 是兩種不同的 obj 格式,如 MSVC、GCC 是用 COFF BCPP、Digital Mars C 用的是 OMF,不過 MS 的 linker 通吃就是了 好了,工具都備齊了,接下來看一下原始碼,請看以下的 crc32.c 看的懂看不懂都沒關係,聞香一下,反正只要會 compile 就好 另外還要幫 DLL 弄一個進入點,有需要的話可以做一些初始化的動作 不過目前就什麼事都不要做,直接傳回 1 表示 ok 就好,請看 entry.c 開始 compile 吧,很簡單,一行就好: \Dev-Cpp\bin\gcc -c -O crc32.c entry.c 這樣 crc32.o 和 entry.o 兩個 obj 檔就跑出來了 接下來重頭戲是 link,除了要指定 /dll 外,還要指明 /entry:DllEntryPoint 因為我們不是用標準的方式,所以 linker 會找不到預設的進入點,一定要指明才行 最後要加的就是提供給外部呼叫的函式名稱,在這裡只有一個 /export:CRC32 全部總合起來像這樣: link crc32.obj entry.o /dll /entry:DllEntryPoint /export:CRC32 除了跑出 crc32.dll 外,連 crc32.lib 也很貼心的提供好了,不過我們用不到...殺吧 辛苦了這麼久,crc32.dll 終於做好了,趕快來測試看看(當然是用 AutoIt) 注意函式是用 C 語言寫的,要用 cdecl 方式呼叫 $Ret=DllCall("crc32.dll","uint:cdecl","CRC32","str","123456789","int",9) MsgBox(0,'CRC32',Hex($Ret[0])) 顯示結果:CBF43926 去 http://www.lammertbies.nl/comm/info/crc-calculation.html 對照一下 一模一樣,成功!! 附帶一提,如果不用 gcc,用其它 compiler 行嗎?來試試 Digital Mars C 好了: \dm\bin\dmc -c -O crc32.c 成功!這時的 obj 檔叫做 crc32.obj,試試 link: link crc32.obj entry.o /dll /entry:DllEntryPoint /export:CRC32 除了跑出 converting object format from OMF to COFF 訊息外,其它一切正常 測試結果也是 ok 的 為了服務到不用 gcc 或 compile 不出 entry.c 的人,這裡提供 compile 好的 entry.o 按照上述的方式可配合自己愛用的 compiler 製作 DLL http://sharebee.com/651b891e (如果免空掛了,下面有 HEX 版本) 總而言之,不管原始碼從哪裡來的,只要能想辦法 compile 成 obj 就能用 linker 製成可供 AutoIt 或 AutoHotKey 呼叫的 DLL 大幅提升了 Script 的彈性和擴充性喔! 以下是這個教學用到的檔案內容,請自行 copy & paste // 檔名: crc32.c // Prototypes of CRC32 functions // Made by Laszlo // Modify by Ward for DLL tutorial typedef unsigned long uint; void CRC32_Init(uint* table) { uint i, j, poly = 0xEDB88320, CRC; for(i = 0; i < 256; i++) { CRC = i; for(j = 0; j < 8; j++) if(CRC & 1) CRC = (CRC >> 1) ^ poly; else CRC >>= 1; table[i] = CRC; } } uint CRC32(unsigned char* buffer, uint len) { static uint table[256]; uint crc32val = -1; uint i; CRC32_Init(table); for (i = 0; i < len; i++) crc32val = table[(crc32val ^ buffer[i]) & 255] ^ (crc32val >> 8); return ~crc32val; } // 檔名: entry.c __stdcall int DllEntryPoint(int hinstDLL, int fdwReason, int lpvReserved) { return 1; } // 檔名: entry.zip,如果上面的免空掛了,想辦法把以下 HEX 存成檔案後解壓吧 504B03041400000008003031873941CB79EAA00000006601000007000000656E747279 2E6F858F310AC2401045FF64B5911456D69E60414F90423B0B1B4BD1A8AB049608660B ED6C050B0FE0412CC5BB780D7536045C5D923CF8CCC0FC19E68F48C07265B5F2AE49D2 A8BDC19736EB8C5FBAC05CAE6213A39A08B8CB4596A18623FB26A7E78DB89F3E425C18 B94EB42AE6AF37B021959ADD412EFF761B4525FE2A20FFB69BC78E05859EC7CD12E41E FF8E9B4394783AACD940EBA1FD74BC4D5213F5FAF800504B0102140014000000080030 31873941CB79EAA000000066010000070000000000000000002000000000000000656E 7472792E6F504B0506000000000100010035000000C50000000000 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 125.225.4.44 ※ 編輯: ward 來自: 125.225.4.44 (12/07 06:46)

12/08 09:14, , 1F
太專業了~~~~ 這個學校應該學不到吧!!! @@
12/08 09:14, 1F

12/09 01:07, , 2F
有看有推~~ ^^
12/09 01:07, 2F
文章代碼(AID): #19ElqsAT (EzHotKey)
文章代碼(AID): #19ElqsAT (EzHotKey)