1

私のプロジェクトでは、Windowsアプリケーションとdllがあります。私はdllを書いたので:

library MyDLL;

uses
  System.SysUtils,
  System.Classes;

{$R *.res}

function Prova: string; export;
begin
  result := 'prova';
end;

exports Prova;

begin
end.

そしてメインプログラムで私はルーチンを呼んだので:

unit FrmMain;

interface

uses
 // declaration uses // 

function Prova: string; external 'MyDLL.dll';

type    
 // declaration type //

implementation

begin
  ...
  TAdvEdit1.Text := Prova;  // [1] // 
  ...
end;

end.

すべてのプロジェクトをコンパイルすると、エラーが報告されず、ステータスが成功を報告しますが、アプリケーションが起動しません。[1]の行を削除すると、正しく機能します。一般に、Prova関数を呼び出してもアプリケーションは起動しません。この問題を解決するにはどうすればよいですか?どうもありがとう。

4

2 に答える 2

3

説明する動作は、アプリケーションの読み込みに失敗したときに発生する動作です。デバッガーから実行すると、サイレントエラーが発生します。デバッガーなしで実行すると、「アプリケーションを初期化できませんでした...」というエラーメッセージが表示されます。これで詳細がわかります。

あなたの場合、考えられる原因は、DLLの依存関係をライブラリローダーで解決できないことであると思われます。そのため、外部関数の呼び出しが削除されたときにアプリが実行されます。その呼び出しを削除すると、外部DLLへの依存関係も削除されます。DLLをロードできることを確認して、問題を解決します。たとえば、実行可能ファイルと同じディレクトリに配置します。

デバッガーからのサイレントエラーはかなりイライラします。何度か経験すると、何をすべきかがわかります。デバッガーなしで実行して、実際に何が問題になっているのかを調べます。

また、モジュールの境界を越えてマネージドDelphi文字列を渡さないことをお勧めします。これにより、実行可能ファイルとDLLの両方に同じコンパイラを使用する必要があります。その制約を受け入れる場合は、パッケージを使用することもできます。コードがそのままの状態で機能するには、ShareMemを使用する必要があります。しかし、私はそれをお勧めしません。

于 2012-11-11T14:06:23.523 に答える
2

プログラムとDLLには別々のメモリマネージャがあります。原則として、DLLから割り当てられたメモリは、アプリケーション内で使用しないでください(逆も同様です)。割り当てはどこから来ますか?Delphiでは、「文字列」は管理対象タイプです。つまり、文字列変数(この場合は結果:='prova')にテキストを割り当てると、Delphi(舞台裏)はDLLのメモリマネージャを使用してその文字列にメモリを割り当てます。次に、たとえば、メインアプリケーション内で他のテキスト値を割り当てる場合、再割り当てではアプリケーションのメモリマネージャーが使用されますが、これは不良です。つまり、アプリのMMは、割り当てられていないメモリにアクセスしています。

この問題を解決するには、USES句の最初のユニットとして「SimpleShareMem」(Delphi> = 2010 IIRC?)ユニットをアプリケーション(.dprファイル)およびDLLに含める必要があります。

library MyDLL;

uses
  SimpleShareMem, // **MUST BE THE FIRST UNIT**
  System.SysUtils,
  System.Classes;
...


program YourApp;

uses
  SimpleShareMem, // **MUST BE THE FIRST UNIT**
  // declaration uses // 

このアプローチの例は、「スタート>プログラム> EmbarcaderoRADStudio>サンプル>Delphi>RTL>SimpleShareMem」にあります。

PCHARを使用して、DLLとAPPの間で文字列を転送することもできます。

于 2012-11-11T12:18:32.877 に答える