DLL の作成は通常、次の手順に分かれています。
1 DLL プロジェクトにプロシージャまたは関数を記述する
2 Exports キーワードを記述し、その下にプロシージャの名前を記述します。パラメーターを記述したり、サフィックスを呼び出したりする必要はありません。
渡された 2 つのパラメータ
1 パラメータの型は、ウィンドウ C++ のパラメータの型と一致している必要があります。 DELPHI データ型は使用しないでください。
2 呼び出しの成功または失敗、またはステータスを報告するには、[プロシージャであっても] 戻り値を用意するのが最善です。成功または失敗の戻り値は、つまり、Windows C++ と互換性があるため、1 [成功] または 0 [失敗] であることが好ましい。
3 stdcall でサフィックスを宣言します。
4 できれば大文字と小文字を区別します。
5 遠方通話サフィックスを使用する必要はありません。これは Windows 16 ビット プログラムとの互換性のためだけに使用されます。
3 つの DLL の初期化と終了クリーンアップ [初期化と終了クリーンアップが必要な場合]
1 DLLPROc [SysUtils ユニットのポインター] は DLL への入り口です。ここで、そのエントリを関数に置き換えることができます。ただし、関数は次の要件 (実際にはコールバック関数) を満たしている必要があります。次のように:
プロシージャ DllEnterPoint(dwReason: DWord);far;stdcall;
dwReason パラメータには 4 つのタイプがあります。
DLL_PROCESS_ATTACH: プロセスの開始時
プロセス終了時の DLL_PROCESS_DETACH
スレッドが入ったときの DLL_THREAD_ATTACH
DLL_THREAD_DETACH スレッド終了時
初期化セクションに次のように書きます。
DLLProc := @DLLEnterPoint;
DllEnterPoint(DLL_PROCESS_ATTACH);
2 フォーム上に TdcomConnection コンポーネントがある場合は、Uses Activex を使用し、初期化中に CoInitialize (nil) を書き込みます。
3 終了時に DcomConnection.Connected := False になり、データ セットが閉じられていることを確認します。それ以外の場合、報告されたアドレスは間違っています。
4 つのグローバル変数の使用
Widnows 32 ビット プログラムでは、2 つのアプリケーションのアドレス空間は相互に関連しません。 DLL はメモリ内のコピーですが、変数は各プロセスのアドレス空間にあるため、メモリ イメージ ファイルを使用しない限り、DLL のグローバル変数を使用して 2 つのアプリケーション間でデータを転送することはできません。
5. 静的ロードを呼び出す
1 クライアント関数の宣言:
1) 大文字と小文字が区別されます。
2) DLL 内の宣言と同じ。
例: showform(form:Tform);Far;external'yproject_dll.dll';
3) 呼び出し時に渡されるパラメータの型は Windows C++ と同じである必要があります。
4) 呼び出すとき、DLL は次の順序で Windows 検索パスに存在する必要があります。
動的ロードへの 6 回の呼び出し
1 プロシージャ タイプを作成します [プロシージャ タイプ変数が単なるポインタであるという性質を理解していれば、何が起こっているかがわかるでしょう]。のように:
タイプ
mypointer=procedure(form:Tform);遠い;外部;
変数
ヒンスト:ハンドル;
ショーフォーム:マイポインタ;
始める
Hinst:=loadlibrary('yproject_dll');//Dll をロードし、ファイル名で検索します。
showform:=getprocaddress(Hinst,'showform');//大文字と小文字を区別して関数名で検索します。オートメーション オブジェクトの性質を理解していれば、これは明らかです。
showform(application.mainform);//関数エントリ ポインタを見つけるときに呼び出されます。
無料ライブラリ(Hinst);
終わり;
7. DLL に TForM を作成します
1 フォームを DLL に使用し、フォームで使用される関連ユニットも使用する必要があります。[これが最も厄介な点です。フォームには多くの特殊なユニットや関数が使用されている可能性があるためです。]
2 Application パラメータを渡し、それを使用してフォームを作成します。
8. DLL に TMDIChildForM を作成します。
1 Dll 内の MDIForm.FormStyle は fmMDIChild である必要はありません。
2 CreateForm の後に次の 2 つの文を記述します。
関数 ShowForm(mainForm:TForm):整数;stdcall
変数
フォーム1: TForm1;
ptr:PLongInt;
始める
ptr:=@(Application.MainForm);//まず DLL の MainForm ハンドルを保存します。解放する必要はなく、置き換えるだけです。
ptr^:=LongInt(mainForm);//DLL の MainForm を呼び出し側プログラムの mainForm に置き換えます。 MainForm は、アプリケーション内のフォーム リソースを特に管理する特別な WINDOW です。
//Application.MainForm := mainForm を直接実行しない理由は、Application.MainForm が読み取り専用プロパティであるためです。
Form1:=TForm1.Create(mainForm);//パラメータを指定して作成
終わり;
注: パラメータは呼び出し側プログラムの Application.MainForm です。
9 つの例:
DLLソースコード:
ライブラリプロジェクト2;
用途
システムユーティリティ、
授業、
ダイアログ、
フォーム、
'Unit2.pas' {Form2} の Unit2;
{$R *.RES}
変数
ccc: Pchar;
プロシージャ OpenForm(mainForm:TForm);stdcall;
変数
フォーム1: TForm1;
ptr:PLongInt;
始める
ptr:=@(アプリケーション.メインフォーム);
ptr^:=LongInt(mainForm);
Form1:=TForm1.Create(mainForm);
終わり;
プロシージャInputCCC(Text: Pchar);stdcall;
始める
ccc := テキスト;
終わり;
プロシージャ ShowCCC;stdcall;
始める
ShowMessage(String(ccc));
終わり;
輸出
オープンフォーム;
入力CCC、
CCCを表示;
始める
終わり。
呼び出し元のソースコード:
ユニットユニット1;
インタフェース
用途
ウィンドウ、メッセージ、SysUtils、クラス、グラフィックス、コントロール、フォーム、ダイアログ、
StdCtrls;
タイプ
TForm1 = クラス(TForm)
ボタン 1: T ボタン;
ボタン 2: T ボタン;
編集1: TEdit;
プロシージャ Button1Click(送信者: TObject);
プロシージャ Button2Click(送信者: TObject);
プライベート
{プライベート宣言}
公共
{公的宣言}
終わり;
変数
フォーム1: TForm1;
実装
{$R *.DFM}
プロシージャ OpenForm(mainForm:TForm);stdcall;外部 'project2.dll';
プロシージャ ShowCCC;stdcall;外部'project2.dll';
プロシージャInputCCC(Text: Pchar);stdcall;外部'project2.dll';
プロシージャ TForm1.Button1Click(送信者: TObject);
変数
テキスト: Pchar;
始める
テキスト := Pchar(Edit1.Text);
// OpenForm(Application.MainForm);//MDICHILD を調整するため
InputCCC(Text);//DLL 内のグローバル変数がさまざまなアプリケーション間で共有されるかどうかを実験するため
終わり;
プロシージャ TForm1.Button2Click(送信者: TObject);
始める
ShowCCC;//これは、WINDOWS 32 ビット アプリケーション DLL のグローバル変数もアプリケーション アドレス空間にあることを示しています。16 ビット アプリケーションは異なる可能性があり、実験は行われていません。
終わり;