2009-04-08 88 views
1

我有一個主要的應用程序和一個類型庫包含2個COM對象,一個是IFile,一個是IFiles。 IFiles創建IFile,並將它們存儲在TLIST中,並具有標準方法,如Add,Remove等.File和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; 

在主應用程序我有測試這樣的代碼。 [代碼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; 

從第二環路,儘管fFiles.Count = 4,但所有內容已丟失。在IFile中我需要一些額外的處理來處理AddRef和Release嗎?或者我寫的IFiles.Add方法是錯誤的?

回答

8

嘗試使用TInterfaceList而不是TList來存儲IFile的實例。這可能會解決您的問題。

+0

啊哈。 TInterfaceList。 – Darkerstar 2009-04-08 06:34:31

0

如果沒有對它的引用,COM對象會自動釋放。 在代碼1中,COM對象在「結束」語句中釋放。

我認爲你需要創建一個包裝對象,並且該包裝對象是你添加到文件中的東西。

在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列表中,因此最好在IFiles.Add內撥打_AddRef,而不是等到它返回。

當您清除列表或者從列表中刪除項目時,您需要在所有接口引用上調用_Release

Toby's answer給出了更好的主意:使用TInterfaceList來存儲接口列表。 TList根本不適合自己的任務。

最後一條建議:名稱上的「I」前綴用於表示接口類型。接口沒有自己的方法實現。您已經展示了IFiles.Add的實現,因此IFiles顯然不是接口類型。它應該被命名爲TFiles,或者TFileList