2009-04-08 9 views
1

私はメインアプリケーションを持っていて、タイプライブラリには2つのCOMオブジェクトがあり、1つはIFile、もう1つはIFilesです。 IFilesはIFileを作成し、TLISTに格納し、追加、削除などの標準的なメソッドを持っています.IFileとIFilesの両方がTAutoObjectです。何とかCOMオブジェクトインスタンスが失われる

IFilesの「追加」メソッドがうまくいけば、単にIFileオブジェクト[コード1]を作成し、それをTListに追加します。問題は、IFileオブジェクトのインスタンスが非常に奇妙な方法で失われることです。私はこのようなテスト・コードを有するメインアプリで[コード2]

[コード1]

function IFiles.Add(AFilename: String): IFile; 
begin 
    Result := CoIFile.Create; 
    Result.Filename := AFilename; 
    // ShowMessage(IntToStr(Result._AddRef)); 
    fFiles.Add(@Result); 
end; 

参照。 fFiles.Count = 4が、すべての内容が失われているにもかかわらず [コード2]第2ループから

var 
    i: Integer; 
    f: IFile; 
    Files: IFiles; 
begin 
    Files := CoTIFile.Create; 
    for i:= 1 to 4 do 
    begin 
    // Create a dummy file object 
    f := Files.Add('Filename ' + IntToStr(i)); 
    f._AddRef; // Not sure if AddRef works like this 
    // Prints out the last file 
    Memo1.Lines.Add(Files.Files[i-1].Filename); 
    end; 

    for i:= 0 to Files.Count-1 do 
    begin 
    f := Files.Files[i]; 
    // F is nil at all time. 
    if (f<>nil) then Memo1.Lines.Add(f.Filename); // ! No print out. 
    end; 
end; 

、。 AddRefとReleaseを処理するためにIFileで特別な処理が必要ですか?または私が書いたIFiles.Addメソッドの方法が間違っていますか?

答えて

8

IFileのインスタンスを格納するために、TListではなくTInterfaceListを使用してみてください。これはあなたの問題を解決するかもしれません。あなたの元のコードで

+0

Aha。 TInterfaceList。 – Darkerstar

0

COMオブジェクトは、参照がない場合は自動的に解放されます。 コード1では、COMオブジェクトは "end"ステートメントで解放されます。

私はあなたがラッパーオブジェクトを作成する必要があり、そのラッパーオブジェクトはファイルに追加するものだと思います。

sory私はすぐにサンプルを作成する時間がありません。

1

問題は、あなたがリストにIFileポインタを追加したが、後でリストから値を読んだとき、あなたは別のIFile変数への直接のポインタを割り当てられていることでした。だから、本来はPIFileという値がIFileという変数に格納されていたのです。 Delphiでは、一般に、タイプなしのPointerタイプを、インタフェースを含むポインタ型のタイプに割り当てることができます。

は、あなたがこのような第二のルック何かを書く必要があるだろう、あなたの元のコードを修正するには、次の

var 
    p: Pointer; 

for i := 0 to Pred(Files.Count) do begin 
    p := Files.Files[i]; 
    if not Assigned(p) then 
    continue; 
    f := IFile(p^); 
    if not Assigned(f) then 
    continue; 
    Memo1.Lines.Add(f.Filename); 
end; 

あなたはあなたの最初のループでf._AddRefを呼び出すことが正しかったです。 IFiles.Addが返された場合、ループの値は実際の参照ではなくポインタであるため、結果の参照カウントは1になります。 fは他の値に再利用されるため、参照カウントを増やす必要があります。手動でカウントしている参照はFFilesリストに格納されているので、_AddRefIFiles.Addに返すことをお勧めします。

リストを消去するとき、またはリストからアイテムを削除するときに、すべてのインタフェース参照で_Releaseに電話する必要があります。

ただし、Toby's answerの方がより良いアイデアが得られます。TInterfaceListを使用して、インターフェイスのリストを保存します。 TListは、単にタスク自体には適していません。

最後のアドバイス:名前の「I」という接頭辞は、のインタフェースのタイプを示すために使用されます。インタフェースには独自のメソッド実装がありません。IFiles.Addの実装を示しているので、IFilesは明らかにインターフェイスタイプではありません。代わりにTFiles、またはおそらくTFileListという名前にする必要があります。

関連する問題