powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Не выходит сделать прослойку между IStream и IStream: Access violation.
25 сообщений из 25, страница 1 из 1
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39668663
SoulStream
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Понадобилось сделать "прослойку" между IStream и IStream. Применений планируется много разных, но в качестве минимального тестирования - пытаюсь засунуть в GDI+.
Лезут ошибки от AV 00300308 до AV 00000000 и AV 00000001... Не мог понять в чём дело, подумал, выкинул весь собственный функционал "прослойки" оставил лишь "базу" - а фик, всё равно падает.

Подскажите пожалуйста, что же ему не так? Я ж уже всё выкинул и сейчас уже просто перенаправляю вызовы, откуда там взяться AV?:
Проверка прослойки
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
unit Unit1;

interface

uses
    System.SysUtils, System.Classes, System.Win.ComObj,
    Vcl.Forms, Vcl.StdCtrls, Vcl.Controls, Vcl.ExtCtrls,
    Winapi.ActiveX, Winapi.ShLwApi,
    Unit2;

type
    TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
    private
    public
    end;

var Form1: TForm1;

implementation

uses GDIPAPI;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
    Stream: IStream; Wrapper: IStreamWrapper;
    GPSI: GdiplusStartupInput; GPToken: Cardinal; GPPicture: GpImage; GPCanvas: GpGraphics;
begin
GPSI.GdiplusVersion:=1;
GPSI.DebugEventCallback:=Nil;
GPSI.SuppressBackgroundThread:=False;
GPSI.SuppressExternalCodecs:=False;
if (Ok<>GdiplusStartup(GPToken, @GPSI, Nil)) then raise Exception.Create('GdiplusStartup Failed');
OleCheck(SHCreateStreamOnFile('C:\<...>\<...>.jpg', STGM_READ, Stream));
Wrapper:=IStreamWrapper.Create(Stream);
if (Ok<>GdipLoadImageFromStream(Wrapper, GPPicture)) then raise Exception.Create('GdipLoadImageFromStream Failed');
if (Ok<>GdipCreateFromHWND(Handle, GPCanvas)) then raise Exception.Create('GdipCreateFromHWND Failed');
if (Ok<>GdipDrawImage(GPCanvas, GPPicture, 0, 0)) then raise Exception.Create('GdipDrawImage Failed');
GdipDisposeImage(GPPicture);
GdipDeleteGraphics(GPCanvas);
GdiplusShutdown(GPToken);
Wrapper:=nil;
Stream:=nil;
end;

end.

Прослойка
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
unit Unit2;

interface

uses Winapi.Windows, Winapi.ActiveX;

type
    IStreamWrapper = class(TInterfacedObject, IStream)
    private
        OrigStream: IStream;
    public
        constructor Create(Stream: IStream);
        destructor Destroy(); override;
        {$IFDEF FPC} // у Делфи и Лазаруса разное описание IStream
            function Stat(out statstg: TStatStg; grfStatFlag: Longint): HRESULT; stdcall;
            function Seek(dlibMove: LargeUInt; dwOrigin: Longint; out libNewPosition: LargeUInt): HRESULT; stdcall;
            function Read(pv: Pointer; cb: DWORD; pcbRead: PDWORD): HRESULT; stdcall;
            function Write(pv: Pointer; cb: DWORD; pcbWritten: PDWORD): HRESULT; stdcall;
            function SetSize(libNewSize: LargeUInt): HRESULT; stdcall;
            function CopyTo(stm: IStream; cb: LargeUInt; out cbRead: LargeUInt; out cbWritten: LargeUInt): HRESULT; stdcall;
            function Commit(grfCommitFlags: Longint): HRESULT; stdcall;
            function Revert(): HRESULT; stdcall;
            function LockRegion(libOffset: LargeUInt; cb: LargeUInt; dwLockType: Longint): HRESULT; stdcall;
            function UnlockRegion(libOffset: LargeUInt; cb: LargeUInt; dwLockType: Longint): HRESULT; stdcall;
            function Clone(out stm: IStream): HRESULT; stdcall;
        {$ELSE}
            function Stat(out statstg: TStatStg; grfStatFlag: Cardinal): HRESULT; stdcall;
            function Seek(dlibMove: Int64; dwOrigin: Cardinal; out libNewPosition: UInt64): HRESULT; stdcall;
            function Read(pv: Pointer; cb: Cardinal; pcbRead: PFixedUInt): HRESULT; stdcall;
            function Write(pv: Pointer; cb: Cardinal; pcbWritten: PFixedUInt): HRESULT; stdcall;
            function SetSize(libNewSize: UInt64): HRESULT; stdcall;
            function CopyTo(stm: IStream; cb: UInt64; out cbRead: UInt64; out cbWritten: UInt64): HRESULT; stdcall;
            function Commit(grfCommitFlags: Cardinal): HRESULT; stdcall;
            function Revert(): HRESULT; stdcall;
            function LockRegion(libOffset: UInt64; cb: UInt64; dwLockType: Cardinal): HRESULT; stdcall;
            function UnlockRegion(libOffset: UInt64; cb: UInt64; dwLockType: Cardinal): HRESULT; stdcall;
            function Clone(out stm: IStream): HRESULT; stdcall;
        {$ENDIF}
    end;

implementation

constructor IStreamWrapper.Create;
begin
OrigStream:=Stream;
end;

destructor IStreamWrapper.Destroy;
begin
OrigStream:=nil;
inherited;
end;

function IStreamWrapper.Stat;
begin
Result:=OrigStream.Stat(statstg, grfStatFlag);
end;

function IStreamWrapper.Seek;
begin
Result:=OrigStream.Seek(dlibMove, dwOrigin, libNewPosition);
end;

function IStreamWrapper.Read;
begin
Result:=OrigStream.Read(pv, cb, pcbRead);
end;

function IStreamWrapper.Write;
begin
Result:=STG_E_UNIMPLEMENTEDFUNCTION;
end;

function IStreamWrapper.SetSize;
begin
Result:=STG_E_UNIMPLEMENTEDFUNCTION;
end;

function IStreamWrapper.CopyTo;
begin
Result:=STG_E_UNIMPLEMENTEDFUNCTION;
end;

function IStreamWrapper.Commit;
begin
Result:=STG_E_UNIMPLEMENTEDFUNCTION;
end;

function IStreamWrapper.Revert;
begin
Result:=STG_E_UNIMPLEMENTEDFUNCTION;
end;

function IStreamWrapper.LockRegion;
begin
Result:=STG_E_UNIMPLEMENTEDFUNCTION;
end;

function IStreamWrapper.UnlockRegion;
begin
Result:=STG_E_UNIMPLEMENTEDFUNCTION;
end;

function IStreamWrapper.Clone;
begin
Result:=STG_E_UNIMPLEMENTEDFUNCTION;
end;

end.


Кстати зачем они задекларировали кучу параметров как "out"? Туда же передаётся указатель, и довольно часто передаётся NULL.
Ни я не могу нормально NULL передать, ни нормально проверить что мне передали NULL... Нафига вот NULLABLE параметр декларировать через "out"?
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39668739
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SoulStreamПонадобилось сделать "прослойку" между IStream и IStream.Зачем?
SoulStream . Нафига вот NULLABLE параметр декларировать через "out"? Это вопрос к эмбаркадере, которая так проимпортила заголовки
SoulStream Ни я не могу нормально NULL передать,
Код: pascal
1.
Pointer(nil)^


SoulStream ни нормально проверить что мне передали NULL
Код: pascal
1.
if @InVar = nil then
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39668792
SoulStream
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Получаем IStream от какой-нибудь библиотеки/объекта и нам надо передать информацию из этого IStream в другую библиотеку/объект (тоже принимающие IStream), но с некоторыми модификациями.
И ещё столкнулись с ситуациями, что данный нам IStream может не иметь реализаций для CopyTo/Clone и прочих - возвращает STG_E_UNIMPLEMENTEDFUNCTION и всё тут.

Но какая разница зачем, я же сейчас убрал все свои модификации - почему не рабоатет даже простое перенаправление?? Наверное это я не учёл какой-то нюанс, но какой? Кто-то может направить?

to _Vasilisk_
Не только к Эмбаркадере, Лазарус/FPC туда же, даже JEDI. Понятно что вопрос к ним, а я просто возмущаюсь))
Интересно что форумчане думают на этот счёт. Ну и вдруг разработчики прочитают меня и пересморят.
_Vasilisk_
Код: pascal
1.
[src delphi]if @InVar = nil then

Сейчас так и делаю, но ИМХО это выглядит коряво.
_Vasilisk_
Код: pascal
1.
Pointer(nil)^

Не-а. Во-первых выглядит тоже хреново. Во-вторых так как раз не работает:
DelphiE2033 Types of actual and formal var parameters must be identicalLazarusError: Call by var for arg no. 3 has to match exactly: Got "untyped" expected "...."Приходится вот так:
Код: pascal
1.
PUInt64(nil)^

или так:
Код: pascal
1.
PLargeUInt(nil)^

...или ещё как... И в разных местах приходится писать по-разному... Выглядит ваще коряво.
И вообще есть мнение что если в коде используется символ ^ то код скорее всего "не очень хороший". В описании типа данных символ ^ - это нормально. Но не в самом исполняемом коде.
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39668826
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SoulStreamВо-вторых так как раз не работает:Я имел в виду, что вместо Pointer нужно подставить указатель на тот тип, который требуется
SoulStreamНаверное это я не учёл какой-то нюанс, но какой?Только, что заметил, что вы сделали. Запомните НИКОГДА не смешивайте работу с классовыми и интерфейсными объектами. Если у вас есть объект, то вы работаете с ним или только как с классом, или только как с интерфейсом (смешивать можно, но нужно четко понимать, что вы делаете и что при этом происходит).

Вот так все будет работать
Код: pascal
1.
2.
3.
4.
5.
var
  Stream: IStream; 
  Wrapper: IStream;
  GPSI: GdiplusStartupInput; GPToken: Cardinal; GPPicture: GpImage; GPCanvas: GpGraphics;
begin



И еще, если не хотите, чтобы вас били, а хотели бы, чтобы вас понимали - придерживайтесь стандартных правил именования. Имена классов начинаются с T, а интерфейсов с I. Так, что в срочном порядке переименуйте ваш класс в
Код: pascal
1.
TStreamWrapper = class(TInterfacedObject, IStream)
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39668836
ziv-2014
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SoulStream,
У тебя OrigStream становится nil. Ты где-то либо стек портишь. У тебя обнуляется Wrapper, вызывается конструктор, с муссором по RefCount, а после вызываются операции с интерфейсом, которые приводят к AV.
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39668840
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ziv-2014У тебя OrigStream становится nil. Ты где-то либо стек портишь.У него после первого же
SoulStream
Код: pascal
1.
2.
if (Ok<>GdipLoadImageFromStream(Wrapper, GPPicture))
    then raise Exception.Create('GdipLoadImageFromStream Failed');

уничтожается Wrapper, потому, что это у него объектная ссылка
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39668847
ziv-2014
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,
Ага заметил, так не стоит делать, из-за этого вся боль :)
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39669208
SoulStream
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
У тебя OrigStream становится nil.ну... Я ставил проверку на Assigned, она не срабатывала.
после первого же Не после первого же)))
Мне надоело тыкать F8 и я прикрутил банальное логирование в TMemo: внутри GdipLoadImageFromStream() начинается работа с IStream и успевало вызвать методы аж 8 раз - ток потом вылетало.
А вот до сравнения с "Ok" не доходило даже. Теперь он делает 20 вызовов и завершается успешно. Спасибо вам огромное!
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39669348
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SoulStream,

что бы все методы вручную не проксировать про Implements погугли

PS: только с XE3
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39669399
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)PS: только с XE3В 2006 уже работало.

Но ему нужно именно, что переопределить методы
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39669403
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SoulStreamНе после первого же)))То, что память сама не затиралась после первого вызова - чистая случайность. Деструктор StreamWrapper вызывался сразу же
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39669424
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_kealon(Ruslan)PS: только с XE3В 2006 уже работало.

Но ему нужно именно, что переопределить методы
правильно оно работает только с XE3, где-то была ветка с разбором
ему там пару методов переопределить, а не все
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39669550
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)где-то была ветка с разборомМоя это ветка была
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39669559
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

ну тогда тем более должен знать, что оно не работает нормально
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39671147
SoulStream
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Про чего погуглить? По одному слову как-то не особо выходит. И я так и не понял - "работает" или "не работает"?))


Делаю примерно так:
Код: pascal
1.
2.
3.
4.
5.
var Wrapper: IStream;
...
Wrapper:=TStreamWrapper.Create(Stream);
...
TStreamWrapper(Wrapper).SomeFieldOrProperty:= ...

В Делфи работает, а вот в Лазарусе не работает. Компилируется с warning'ом и просто не фурычит, пришлось переделать так:
Код: pascal
1.
2.
3.
4.
5.
var Wrapper: IStream;
...
Wrapper:=TStreamWrapper.Create(Stream);
...
(Wrapper as TStreamWrapper).SomeFieldOrProperty:= ...

И так уже работает и там и там. Кто-то сможет пояснить почему..?
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39671161
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SoulStreamКто-то сможет пояснить почему..?Вам же говорили не смешивать работу с классами и интерфейсами.

Вот этот код
SoulStream
Код: pascal
1.
2.
3.
var Wrapper: IStream;
...
Wrapper:=TStreamWrapper.Create(Stream);

эквивалентен такому
Код: pascal
1.
2.
3.
4.
5.
6.
7.
var
  WrapperObj: TStreamWrapper;
  Wrapper: IStream;
...
WrapperObj:=TStreamWrapper.Create(Stream);
if not WrapperObj.GetInterface(IStream, Wrapper) then
  raise Exception.Create('Interface not supported');

по умолчанию WrapperObj.GetInterface возвращает Self. Но это поведение можно легко изменить. Вот этот код SoulStream
Код: pascal
1.
TStreamWrapper(Wrapper)

говорит: "я знаю, что Wrapper это объект класса TStreamWrapper. Компилятор, верь мне". Далее, если вы не угадали, что это тот объект, то все будет работать. Если не угадали, то получите маловразумительные исключения в произвольных местах кода. Delphi вам верит, а Лазарус выражает сомнения.

Вот этот код
SoulStream
Код: pascal
1.
(Wrapper as TStreamWrapper)

эквивалентен такому
Код: pascal
1.
2.
3.
if not Wrapper is TStreamWrapper then
  raise Exception.Create('Invalid class cast');
TStreamWrapper(Wrapper)....



Т.е. оба варианта плохи. Что делать? Если вам у IStream нужны дополнительные методы/свойства, то нужно поступать так же, как с классами - писать наследника

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
IStreamWrapper = interface(IStream)
  ['{..........}']  // Тут GUID для генерации нажать Ctrl + Shift + G
  // Methods
  // Properties
  property SomeProperty ....
end;

TStreamWrapper = class(TInterfacedObject, IStream, IStreamWrapper)
  .............
end;

var Wrapper: IStreamWrapper;
...
Wrapper:=TStreamWrapper.Create(Stream);
...
Wrapper.SomeFieldOrProperty:= ...
if (Ok <> GdipLoadImageFromStream(Wrapper, GPPicture)) then
  raise Exception.Create('GdipLoadImageFromStream Failed');
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39671236
SoulStream
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
LazarusЕсли не угадали ...
Как ж мне не угадать - я же сам только что создал свой класс. :) Это точно он.
Но Лазарус говорит:
Unit2.pas(Y,X) Warning: Class types "IStream" and "TStreamWrapper" are not relatedИ по факту как бы просто не выполняет "property SomeProperty write FField". При этом Делфи выполняет корректно.
ну... Просто создавал-то я класс, только ссылка на него интерфейсная... не?
Ясно, спасибо большое...

kealon(Ruslan)что бы все методы вручную не проксировать про Implements погугли
...
где-то была ветка с разборомИ всё же про что это? Какая ветка?
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39671239
SoulStream
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Но а если мне нужны ещё и поля? Там, Int64 например, Cardinal, WideString? Интерфейс же мне не позволяет поля.
То есть я лишён возможности делать "property SomeProperty read/write FField", а придётся переписывать исключительно в виде объявления методов get/set во втором интерфейсе, а потом ещё и реализовывать их же уже в TStreamWrapper? :(


гм... А что если я буду просто хранить обе ссылки?:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
var
  WrapperObject: TStreamWrapper;
  WrapperInterface: IStream;
...
WrapperObject:=TStreamWrapper.Create(Stream);
WrapperInterface:=WrapperObject;
...
WrapperObject.SomeProperty:= ...
...
if (Ok<>GdipLoadImageFromStream(WrapperInterface, GPPicture)) then raise Exception.Create('GdipLoadImageFromStream Failed');
...
WrapperInterface:=nil;

Это будет чем-то совсем плохо?
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39671246
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SoulStreamНо а если мне нужны ещё и поля?Поля вообще в любом классе должны объявляться как strict private. И иметь доступ только из класса. Нужен доступ снаружи - объявляйте свойство
SoulStreamпридётся переписывать исключительно в виде объявления методов get/set во втором интерфейсе, а потом ещё и реализовывать их же уже в TStreamWrapper? :(И в чем проблема?
SoulStreamА что если я буду просто хранить обе ссылки?:когда интерфейсная ссылка обнулит счетчик ссылок - объект уничтожится. Вы на это наступили в самом первом посту.

Хорошо, вот вариант для ленивых
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
TStreamWrapper = class;

IStreamWrapper = interface(IStream)
  ['{..........}']  // Тут GUID для генерации нажать Ctrl + Shift + G
  function GetObjectImpl: TStreamWrapper;
  property ObjectImpl: TStreamWrapper read GetObjImpl;
end;

TStreamWrapper = class(TInterfacedObject, IStream, IStreamWrapper)
  .............
  function GetObjectImpl: TStreamWrapper;
end;

function TStreamWrapper.GetObjectImpl: TStreamWrapper;
begin
  Result := Self;
end;

var Wrapper: IStreamWrapper;
...
Wrapper:=TStreamWrapper.Create(Stream);
...
Wrapper.ObjectImpl.SomeFieldOrProperty:= ...


Этот вариант кривой до безобразия, но, по крайней мере, лучше чем хранение двух ссылок. Ну и при вызове метод GetObjectImpl из другой dll могут возникнуть проблемы. Т.е., по сути, это те же разложенные грабли. Правильный наследник самое верное решение
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39671248
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SoulStreamКак ж мне не угадать - я же сам только что создал свой класс. :)Вы создали объект класса и запросили у него интерфейсную ссылку. Делфи вернула вам тот же указатель, Лазарус - другой
SoulStreamИ всё же про что это? Какая ветка? http://www.sql.ru/forum/1165959/izmenilsya-sposob-vyzova-ekzemplyar-klassa-dlya-queryinterface
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39671340
SoulStream
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
_Vasilisk_когда интерфейсная ссылка обнулит счетчик ссылок - объект уничтожится.Это-то я уже понял, но если я буду хранить обе - то полагаю объект сам не обнулится, пока у меня всё ещё хранится интерфейсная?
Это объектная перестанет быть валидной, когда я обнилю интерфейсную - но я же точно знаю, когда я буду это делать.


Впрочем, я подумал и пришёл к мысли - а так ли нужен мне вообще property, почему просто не пользоваться методоми set/get (тем более что их всё равно не сделать private)?

Чем-то будет отличаться это:
Код: pascal
1.
2.
3.
4.
5.
6.
    IStreamWrapper = Interface(IStream)
        ['...']
        ...
    end;
    TStreamWrapper = Class(TInterfacedObject, IStream, IStreamWrapper)
        ...

от вот этого?:
Код: pascal
1.
2.
3.
4.
5.
6.
    IStreamWrapper = Interface(IStream)
        ['...']
        ...
    end;
    TStreamWrapper = Class(TInterfacedObject, IStreamWrapper)
        ...


И ещё тут нашёл/прочитал - советуют всегда использовать safecall, и аргументируют мощно, надо подумать... С:
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39671634
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SoulStreamЧем-то будет отличаться это:Тем, что QueryInterface(IStream) работать не будет. Попробуйте такой код с обоими вариантами

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
var
  Wrapper: IStreamWrapper;
  Strm: IStream;
  Intf: IInterface;
begin
  Wrapper := TStreamWrapper.Create(...);
  Strm := Wrapper;
  Intf := Wrapper;
  OleCheck(Intf.QueryInterface(IStream, Strm));
end;


SoulStreamсоветуют всегда использовать safecallЭто для COM. Там правила жестче. Для внутренней реализации это не обязательно. И будет немного медленнее.
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39671636
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SoulStreamЭто объектная перестанет быть валидной, когда я обнилю интерфейсную - но я же точно знаю, когда я буду это делать.Сейчас будете знать. А через месяц? Если уже делать гибрид, то не храните объектную ссылку вообще. А каждый раз запрашивайте у интерфейса. Оно безопаснее
SoulStreamа так ли нужен мне вообще property, почему просто не пользоваться методоми set/getА какая разница? Тем более, что property можно не объявлять в классе. Достаточно их объявить в интерфейсе
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39671795
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SoulStreamkealon(Ruslan)что бы все методы вручную не проксировать про Implements погугли
...
где-то была ветка с разборомИ всё же про что это? Какая ветка? 17876455
...
Рейтинг: 0 / 0
Не выходит сделать прослойку между IStream и IStream: Access violation.
    #39672770
SoulStream
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо огромное всем! Вроде получилось, работает как задумано, ведётся активное тестирование!
...
Рейтинг: 0 / 0
25 сообщений из 25, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Не выходит сделать прослойку между IStream и IStream: Access violation.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]