Устранение потери экземпляра COM-объекта IFile в программе на Delphi
Вопрос, поднятый в данном контексте, касается потери экземпляра COM-объекта IFile в приложении, использующем типобibliотеку, содержащую два COM-объекта: IFile и IFiles. Объект IFiles создает экземпляры IFile и хранит их в списке. Проблема заключается в том, что, несмотря на успешное создание объектов IFile, они теряются при попытке доступа к ним во второй итерации цикла.
Описание проблемы
В коде метода Add объекта IFiles создается новый экземпляр IFile и добавляется в список. Однако при попытке обращения к объектам в главном приложении, они оказываются потерянными, то есть не могут быть использованы или их состояние не сохраняется.
Код метода Add объекта IFiles
function IFiles.Add(AFilename: String): IFile;
begin
Result := CoIFile.Create;
Result.Filename := AFilename;
fFiles.Add(@Result);
end;
Тестовый код в главном приложении
var
i: Integer;
f: IFile;
Files: IFiles;
begin
Files := CoTIFile.Create;
for i:= 1 to 4 do
begin
f := Files.Add('Filename ' + IntToStr(i));
f._AddRef; // Вызов AddRef для увеличения счетчика ссылок
Memo1.Lines.Add(Files.Files[i-1].Filename);
end;
for i:= 0 to Files.Count-1 do
begin
f := Files.Files[i];
if (f <> nil) then // Объект f всегда равен nil
Memo1.Lines.Add(f.Filename); // Ничего не выводится
end;
end;
Альтернативный ответ
В альтернативном ответе предложено использовать обертку для COM-объектов, которая будет добавляться в список, вместо непосредственного добавления указателя на COM-объект.
Подтвержденный ответ
Рекомендуется использовать TInterfaceList вместо TList для хранения экземпляров IFile. Это может решить проблему потери ссылок на объекты.
Дополнительные замечания
В исходном коде была ошибка при чтении значений из списка: присваивался указатель, а не интерфейс. Исправленный код должен выглядеть следующим образом:
var
p: Pointer;
begin
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;
end;
Также правильно будет вызвать f._AddRef в первом цикле, чтобы увеличить счетчик ссылок на объект IFile, так как метод Add возвращает указатель, а не ссылку на объект. Вызов f._AddRef следует сделать внутри метода Add объекта IFiles.
При удалении элементов из списка необходимо вызвать f._Release для освобождения интерфейсов.
Использование TInterfaceList - это лучший подход, как было указано в ответе Toby.
Заключение
Используя TInterfaceList, вы обеспечите правильное управление ссылками на интерфейсы COM-объектов в вашем приложении на Delphi. Необходимо также следить за правильным использованием методов AddRef и Release для управления жизненным циклом объектов.
Контекст: Пользователь сталкивается с проблемой потери ссылок на экземпляры COM-объектов `IFile` в приложении на Delphi, что приводит к невозможности их использования во второй итерации цикла, несмотря на успешное создание.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.