Interfaces and RTTI Issue: can someone confirm? lazarus / 62-General ---------------------------------------------------------------------- terryc · 2015-12-09 11:44 Hi, I'm using JSON and RTTI to store / load objects from a stream. However, most of my objects are used/accessed by interfaces. In addition, i have hierarchies of objects (and interfaces) to manage complex models. I have found a situation where the RTTI does not seem to set the interface reference properly. An example test project demonstrating this is attached. First there is a IMyObject and TMyObject as the root object. This object will have its "test" property set: 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   TMyObject = class( TInterfacedObject, IMyObject)    private      FTest : IMyInterface;      function GetTest: IMyInterface;      procedure SetTest(AValue: IMyInterface);    published      property Test : IMyInterface read GetTest write SetTest;  end;  Then this test property is used to store an object of type TMyFailedInterface with a deep inheritance: 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   TIntermediate = class( TInterfacedObject, IIntermediateInterface);  TMyFailedInterface = class( TIntermediate, IMyInterface);  the actual code for storing the property is somewhat like this (it uses the intermediate interface as a common ancestor to all interfaces): 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     lInt2 := lInt as IIntermediateInterface;    SetInterfaceProp( lMyObject, 'Test', lInt2);  This actually works since SetInterfaceProp accepts any IUnknown. lInt is of the proper interface type so it should work. However, when accessing the property again, for example to execute a function, a SIGSEGV error occurs: 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    lValue := lMyObject.Test.TestFunction; //this creates a SIGSEGV  There is a workaround, but it's quite annoying to implement, this is to declare ALL interfaces implemented for each class: 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   TMyInterface = class( TIntermediate, IMyInterface, IIntermediateInterface) In that case, the same SetInterfaceProp will work, and the same access to the test property will work. Please see the full test project in attachment for more details. I have tested this on Windows with FPC 32-bit and Lazarus, FPC 3.1.1 SVN 49552. 1°) Can someone duplicate this behaviour? 2°) Is it a bug? Should i register it as such? 3°) Is there a better workaround? Best regards, TerryC ---------------------------------------------------------------------- Graeme · 2015-12-09 12:15 Quote from: terryc on December 09, 2015, 12:44:38 pmHowever, when accessing the property again, for example to execute a function, a SIGSEGV error occurs: 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    lValue := lMyObject.Test.TestFunction; //this creates a SIGSEGV What happens if you use an interface instance to get to TestFunction, instead of the object reference? eg: 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 var  intf: ISomeInterface;begin   ...   if Supports(lMyObject, ISomeInterface, intf) then     intf.TestFunction;   ...end;  ps: I haven't had time to look at your actual attachment. ---------------------------------------------------------------------- terryc · 2015-12-09 12:57 Same result: 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     //This check fails with a SIGSEGV error:    lMyInt2 := lMyObject.Test;    CheckEquals( lValue, lMyInt2.TestFunction, 'should be the same');produces a SIGSEGV! ---------------------------------------------------------------------- Cyrax · 2015-12-09 17:13 You might be interested this FPC branch which have experimental support for RTTI for interfaces. Web view : http://svn.freepascal.org/cgi- bin/viewvc.cgi/branches/interfacertti/?sortby=date&view=log Subversion : http://svn.freepascal.org/svn/fpc/branches/interfacertti ---------------------------------------------------------------------- terryc · 2015-12-09 19:10 Many thanks Cyrax for the answer, i will look at it. Up to now, i've tried to limit myself to production code when using FPC. BTW, there is an easy workaround that seems to work. I need to make more indepth testing but the unit test is OK: it is to give an IUnknown interface to SetInterfaceProp. Instead of giving an intermediate Interface (in my case, it would be an ISerializable), one should downcast the interface to an IUnknown and it works. I've attached the updated Unit test project as a demo. 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 var  lMyInt2      : IMyInterface;  lInt            : IUnknown;  [...]begin  [...]  lInt  := lMyInterface;  SetInterfaceProp( lMyObject, 'Test', lInt);  lMyInt2 := lMyObject.Test;  lValue := lMyInterface.TestFunction;  CheckEquals( lValue, lMyInt2.TestFunction, 'should be the same'); ---------------------------------------------------------------------- Jonas Maebe · 2015-12-15 10:48 Could you create a small sample that does not depend on Lazarus/the LCL, and file an FPC bug report at http://bugs.freepascal.org ? Thanks. ---------------------------------------------------------------------- terryc · 2015-12-16 13:20 yes, I will do that. Best regards, TerryC