IStream Clone method definition lazarus / 67-Windows ---------------------------------------------------------------------- 440bx · 2025-06-25 21:00 Hello, In types.pp, IStream is defined as follows: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   IStream = interface(ISequentialStream) ['{0000000C-0000-0000-C000-000000000046}']     function Seek(dlibMove : LargeInt; dwOrigin : DWORD; out libNewPosition : LargeUInt) : 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 : DWORD) : HRESULT;stdcall;     function Revert : HRESULT;stdcall;     function LockRegion(libOffset : LargeUInt;cb : LargeUInt; dwLockType : DWORD) : HRESULT;stdcall;     function UnlockRegion(libOffset : LargeUInt;cb : LargeUInt; dwLockType : DWORD) : HRESULT;stdcall;     Function Stat(out statstg : TStatStg;grfStatFlag : DWORD) : HRESULT;stdcall;     function Clone(out stm : IStream) : HRESULT;stdcall;  end; In that definition the Clone method's parameter is a pointer to an IStream but, in the C/C++ definition: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i HRESULT Clone(  [out] IStream **ppstm); the parameter is a pointer to a pointer to an IStream. Since FPC's "out" takes care of one pointer level, it seems the Clone method's definition should be: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i      function Clone(out stm : PIStream) : HRESULT;stdcall; Note the change from type "IStream" to "PIStream". Am I misunderstanding something in the types.pp definitions or is the definition of the Clone method incorrect ? ---------------------------------------------------------------------- Fibonacci · 2025-06-25 21:17 Isnt it that the Interface in Pascal is already a pointer, so using "out IStream" effectively gives you an "IStream**" equivalent? ---------------------------------------------------------------------- 440bx · 2025-06-25 21:26 Yes, an interface is a pointer, it is also a pointer in C/C++. Since the Clone method returns a new IStream, which is a new pointer, the argument should be set to the value of that pointer which requires it to be a pointer to a pointer. Part of the problem is, I understand exactly how it works in C/C++.  In FPC, because of the different ways things are defined, I'm not sure if the parameter should be "out IStream" or "out PIStream".  In C/C++ it's crystal clear, in FPC, not so much but, at least at first sight, it looks like it should be "out PIStream". ---------------------------------------------------------------------- 440bx · 2025-06-25 23:20 Quote from: Fibonacci on June 25, 2025, 11:17:04 pmIsnt it that the Interface in Pascal is already a pointer, so using "out IStream" effectively gives you an "IStream**" equivalent? Yes, it does work out that way in FPC. ---------------------------------------------------------------------- Thaddy · 2025-06-26 05:32 That code always works as long as interfaces COM is defined. The code in the RTL is equivalent to the code I wrote for Delphi before 2001. ( and used in Delphi RTL with my permission)  So if there are any problems, blame me and ask me. It is a straight translation of the meaning of the COM IStream interface as far as I remember. It was first published in UNDU. Frankly I do not see any issue. Note the fact that I wrote it, does not mean that I actually use it after those 25 years. This is about the stream wrapper code, which I wrote for Delphi, somebody else did the FPC version. Just in case: this is not subject to clean-rooming code, because it is mine. That means that the Delphi implementation can be copied ad verbatum. ---------------------------------------------------------------------- H₂SO₄ · 2025-06-26 05:56 Quote from: 440bx on June 25, 2025, 11:26:14 pmYes, an interface is a pointer, it is also a pointer in C/C++. I think it's important to differentiate between C and C++ here, since the former doesn't have native class/interface types. After resolving some C-specific preprocessor defines, the definition of  IStream  looks like this in C: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i typedef struct IStreamVtbl {   /*** IUnknown methods ***/  HRESULT (__stdcall *QueryInterface)(IStream *This, REFIID riid, void **ppvObject);  ULONG   (__stdcall         *AddRef)(IStream *This);  ULONG   (__stdcall      *Release)(IStream *This);   /*** ISequentialStream methods ***/  HRESULT (__stdcall           *Read)(IStream *This, void *pv, ULONG cb, ULONG *pcbRead);  // ...} IStreamVtbl; struct IStream {  const IStreamVtbl* lpVtbl;}; typedef struct IStream IStream; IStream  is a struct/record containing instance data (just a VMT pointer to interface methods). IStream *  however is a pointer to instance data, which is equivalent to the definition of  TObject. This also applies to COM interface types in FPC, which follow the same principle (albeit with a different VMT layout). IStream **  would then be comparable to  ^TObject,  and like you've already pointed out, this additional pointer level can be handled by marking the parameter as  var/out. So yes,  IStream ** = out IStream  when translating from C to Pascal. ---------------------------------------------------------------------- Thaddy · 2025-06-26 06:02 So? as I said I wrote it, at least for Delphi. Seems to work for more than 25 years, so point me to the real issue: I can't find it..... NOTHING changed... Give a better example. ---------------------------------------------------------------------- Fibonacci · 2025-06-26 06:10 Quote from: Thaddy on June 26, 2025, 08:02:15 amSo? @Khrys explained very well why "out IStream" equals "IStream**". Case closed, whats your beef? Your answer isnt really an answer, his is. Great explanation, kudos! ---------------------------------------------------------------------- Thaddy · 2025-06-26 06:14 The issue is likely out did not exist when I wrote it and is also very likely incorrect. It should maybe be out nowadays, but I only had var or pointer. I still do not see if this affects code, though..... In this case it should be var, since it can not be nil. ---------------------------------------------------------------------- 440bx · 2025-06-26 06:15 Thank you Khrys.  Nice explanation. Sometimes I get lost in the subtleties of C, C++ and FPC pointer handling.  It takes me a few minutes of thinking to clear the "fog". ---------------------------------------------------------------------- Thaddy · 2025-06-26 06:17 There is no fog. Posts crossed, I changed my post a little. That may explain it. In this case, trust the source. @Khrys Old code is still valid. ---------------------------------------------------------------------- Fibonacci · 2025-06-26 06:33 Quote from: Thaddy on June 26, 2025, 08:17:50 am@Khrys Old code is still valid. And he explained why its valid. Thaddy, you good? Im getting a little concerned here ---------------------------------------------------------------------- Thaddy · 2025-06-26 07:18 Yes, I am good. Discussions about my own code makes me feel like Trump, though.. I understand the concerns of 440bx but it has a time frame.