Wolfgang Chien's Homepage | Delphi學習筆記 - 問答篇 |
請問如何 用bc ++ 製成 dll可否用一個簡單的例子說明... 如果能指出是那本書可參考更好...
又 delphi 如何call dll
由於沒有用 BC++ 寫過 DLL(用 Delphi 倒是寫了一個KeyPro保護DLL), 我想回答 Delphi 如何使用 DLL 的這個部分.
參考資料: 在 Delphi 隨軟體附的參考資料有, 1. Object Pascal Language Guide, 第十二章 2. On-Line Help 以 DLL 為查詢關鍵字, 找Dynamic-Link Libraries (DLLs) 這個 Topic
用是知道怎麼用, 不過要講出來(甚至是鍵成文件), 就有點難了,以下的說明如果寫得不好, 還請各位網友指正:
馬上想得到的使用說明有以下幾點:
![]() |
1. 所需動態連結的 DLL 須置放在與執行檔同一目錄或Windows System 目錄 |
![]() |
2. 確認 DLL export 出來的函式的原型, 以目前的情況而言, 通常只拿得到 C 語言的函數原型, 這時要注意 C 與 object Pascal 相對應的型別, 如果需要, 在 interface 一節定義所需的資料類別 |
![]() |
3. 在 implementation 節中宣告欲使用的函式, 語法大致如下:
procedure ProcName(Argu...); far; external 'DLL檔名'; index n; function FuncName(Argr...): DataType; far; external 'DLL檔名'; index n; 宣告時, index n 如果不寫, 便是參考資料中所謂 import by name 的方式, 此時, 由於需要從 DLL 的 name table 中找出這個函式, 因此, 連結執行速度比 import by ordinal稍慢一些 此外, 還有一種 by new name, 由於我沒用過, 您可以查一參考資料, 大意是可以 import 後改用另一個程式命名呼叫這個函式 |
![]() |
4. 然後, 呼叫與使用就與一般的Delphi 沒有兩樣 |
![]() |
5. 上述是直接寫到呼叫DLL函式的程式單元中, 此外, 也可以將DLL的呼叫宣告集中到一個程式單元(Import unit), Delphi 內附的 WinTypes, WinProcs 是一個例子, 您可以參考一下,同時觀察一下 C 與 Pascal 互相對應的資料型態 |
![]() |
6. 除了上述的 static import 的方式, 另外有一種 dynamic import 的寫法, 先宣告一個程序類型(procedural-type),程式執行時, 以 LoadLibrary() API Load 進來後, 再以 GetProcAddress() API 取得函式的位址的方式來連結呼叫, 在 Object Pascal Language Guide P.132-133 有一個例子, 您可以參考看看 |
如果要舉個例子, 以下是從我以前的程式節錄出來的片斷:
(* for CWindows 3.1 *) unit Ime31; interface uses SysUtils, WinTypes, WinProcs, Dialogs; type (* 必要的資料型態宣告 *) tDateNTime = record wYear, wMonth, wDay: word; wHour, wMin, wSec: word; end; TImePro = record hWndIme: HWnd; { IME handle } dtInstDate: tDateNTime; { Date and time of installation } wVersion: word; { the version of IME } szDescription: array[0..49] of byte; { Description of IME module } szName: array[0..79] of byte; { Module name of the IME } szOptions: array[0..29] of byte; { options of IME at startup } fEnable: boolean; { IME status; True=activated, False=deactivated } end; pTImePro = ^TImePro; function SetIme(const sImeFileName: string): boolean; far; implementation (* begin 呼叫 winnls.dll export 函數的宣告 *) function ImpSetIme(hWndIme: HWND; lpImePro: pTImePro): boolean; far; external 'winnls.dll'; (* end 呼叫 winnls.dll export 函數的宣告 *) (* -------------------------------------------------- *) (* SetIme(const sImeFileName: string): boolean; (* ====== (* 切換到某一特定的輸入法 (* (* 傳入引數: (* sImeFileName: 輸入法 IME 檔名, 例: phon.ime; (* 空字串: 英數輸入法 (* (* 傳回值: (* True: 切換成功 (* False: 失敗 (* -------------------------------------------------- *) function SetIme(const sImeFileName: string): boolean; var pImePro: pTImePro; begin Result := False; if MaxAvail < SizeOf(TImePro) then begin MessageDlg('記憶體不足', mtWarning, [mbOk], 0); Exit; end else begin New(pImePro); try if sImeFileName = '' then (* 空字串, 還原到英數輸入法 *) pImePro^.szName[0] := 0 else StrPCopy(@pImePro^.szName, sImeFileName); Result := ImpSetIme(0, pImePro); (* 呼叫 ImpSetIme *) finally Dispose(pImePro); end; { of try } end; end; { of SetIme } end. { of Unit Win31 }
首頁 | 學習筆記 | 主題公園 | 軟體下載 | 關於本站 | 討論信群 | 相約下次 |