* * *

Author Topic: is and as operators with CORBA interfaces.  (Read 1703 times)

mse

  • Sr. Member
  • ****
  • Posts: 253
Re: is and as operators with CORBA interfaces.
« Reply #15 on: December 27, 2017, 04:14:49 pm »
You write:
Quote from: Thaddy
CORBA is usually a technically bad choice for local interfaces.
which is nonsense.
As ordered:
Code: Pascal  [Select]
  1. program test2;
  2. {$ifdef FPC}{$mode objfpc}{$h+}{$endif}
  3. {$ifdef mswindows}{$apptype console}{$endif}
  4. uses
  5.  {$ifdef FPC}{$ifdef unix}cthreads,cwstring,{$endif}{$endif}
  6.  sysutils;
  7.  
  8. type
  9.  {$interfaces corba}
  10.  
  11.  ivisibility = interface['AA']{0}
  12.   procedure show();
  13.   procedure hide();
  14.  end;
  15.  
  16.  ttest = class(tobject,ivisibility)
  17.   protected
  18.    procedure show();
  19.    procedure hide();
  20.  end;
  21.  
  22.  
  23. { ttest }
  24.  
  25. procedure ttest.show();
  26. begin
  27.  //enter code to show the object here
  28. end;
  29.  
  30. procedure ttest.hide();
  31. begin
  32.  //enter code to hide the object here
  33. end;
  34.  
  35. procedure hideobject(const aintf: ivisibility);
  36. begin
  37.  aintf.hide();
  38. end;
  39.  
  40. var
  41.  test1: ttest;  
  42. begin
  43.  test1:= ttest.create();
  44.  if test1 is ivisibility then begin
  45.   hideobject(test1 as ivisibility);
  46.  end;
  47.  test1.destroy();
  48. end.
  49.  
« Last Edit: December 27, 2017, 04:31:06 pm by mse »

soerensen3

  • Jr. Member
  • **
  • Posts: 64
Re: is and as operators with CORBA interfaces.
« Reply #16 on: December 27, 2017, 09:30:26 pm »
Thanks for all the responses, I was expecting the answer to be a a simple yes or no so I did not bother to write a sample code with my question. But mse already provided the code, which also compiles in fpc 3.04.
@Thaddy: Yes the tutorial is exactly where I came from. I only want to use Corba because I don't want reference counting, because I do my own object management I want to make it simpler so I don't want to use an IDL if possible. If I remember correctly there was something about disabling the reference counting by providing empty procedures bodies to _AddRef and _Release to a COM interface. Also I don't really need to use "is" and "as" as an operator. I only need the functionality. So if there is a function which does the same I don't really mind.
All my interfaces have GUID's by the way. And the interface variables where I get the errror are fields of class instances.

Seeing this
Code: Pascal  [Select]
  1.  itest = interface         ['AA']{0}
confused me a bit.
So the interface GUID is just a unique string for Corba interfaces? What about COM, does it have to be a guid like this? ['{18740D8D-D2E9-4A76-A43D-DFC2057CD2FF}']
« Last Edit: December 27, 2017, 09:37:19 pm by soerensen3 »
Lazarus 1.9 with FPC 3.0.4
Target: Manjaro Linux 64 Bit (4.9.68-1-MANJARO)

Thaddy

  • Hero Member
  • *****
  • Posts: 5387
Re: is and as operators with CORBA interfaces.
« Reply #17 on: December 27, 2017, 09:36:04 pm »
@Thaddy: Yes the tutorial is exactly where I came from. I only want to use Corba because I don't want reference counting, because I do my own object management I want to make it simpler so I don't want to use an IDL if possible. If I remember correctly there was something about disabling the reference counting by providing empty procedures bodies to _AddRef and _Release to a COM interface. Also I don't really need to use "is" and "as" as an operator. I only need the functionality. So if there is a function which does the same I don't really mind.
Then overrride the refcount....These methods are virtual, We also have inheritsfrom, btw ...
High(Methusalem) - 1;

Thaddy

  • Hero Member
  • *****
  • Posts: 5387
Re: is and as operators with CORBA interfaces.
« Reply #18 on: December 27, 2017, 09:47:27 pm »
which is nonsense.
As ordered:
OK works. Add it to the wiki (because it works, complements) . Add too the compiler output with -a specified.
It works contrived. Good. Does it work in practise? No. Does anybody use CORBA locally: Yes, haplorhini... (that is a subspecies of humanoids, primates).

I am not against its use, I am against borderline use and diverting from standards.

Now paying https://en.wikipedia.org/wiki/Once_Bitten%2C_Twice_Shy
« Last Edit: December 27, 2017, 10:14:11 pm by Thaddy »
High(Methusalem) - 1;

soerensen3

  • Jr. Member
  • **
  • Posts: 64
Re: is and as operators with CORBA interfaces.
« Reply #19 on: December 27, 2017, 10:15:33 pm »
By closer look a the example I notice a difference with my code. I have an Interface variable instead of an object variable. This does work with COM interfaces at least.

Code: Pascal  [Select]
  1. program Project1;
  2.  
  3. {$interfaces corba}
  4. type
  5.   IInterface1 = interface ['{D6537088-AA99-4656-B88E-615917CF75BB}']
  6.   end;
  7.   IInterface2 = interface ( IInterface1 ) ['{89493813-85C4-4DF7-86BE-3F6CC3978790}']
  8.     procedure SomeProcedure;
  9.   end;
  10.  
  11. var
  12.   IntfVar: IInterface1;
  13. begin
  14.   {Some assignments to IntfVar}
  15.   if ( IntfVar is IInterface2 ) then
  16.     IInterface2( IntfVar ).SomeProcedure;
  17. end.
  18.  

This gives me the following error: project1.lpr(15,16) Error: Class or COM interface type expected, but got "IInterface1"

Is it wrong to use interfaces like that?
Lazarus 1.9 with FPC 3.0.4
Target: Manjaro Linux 64 Bit (4.9.68-1-MANJARO)

Thaddy

  • Hero Member
  • *****
  • Posts: 5387
Re: is and as operators with CORBA interfaces.
« Reply #20 on: December 27, 2017, 10:25:57 pm »
The error is because it is not a COM interface, but a CORBA interface, which is a bad choice inyour case.

No it is right to use interfaces, but not CORBA interfaces, unless you know the intimate details. That's the whole point I am trying to make all day.
For beginners it is a waste of time. You should use COM. There is hardly any evidence that - without a professional multi-platform necessity - CORBA has any merits.
It works -as shown by MSE - but it is not mainstream. Your code simply works with COM and compiles better.
High(Methusalem) - 1;

soerensen3

  • Jr. Member
  • **
  • Posts: 64
Re: is and as operators with CORBA interfaces.
« Reply #21 on: December 27, 2017, 10:53:30 pm »
Ok but how do I prevent the reference counting in detail?
Do you suggest using TInterfacedPersistent as a base?
I can't open the reference for the _AddRef .. functions. What I got so far..

Code: Pascal  [Select]
  1. program Project1;
  2.  
  3. uses Classes;
  4.  
  5. type
  6.   IInterface1 = interface ( IInterface ) ['{D6537088-AA99-4656-B88E-615917CF75BB}']
  7.   end;
  8.   IInterface2 = interface ( IInterface1 ) ['{89493813-85C4-4DF7-86BE-3F6CC3978790}']
  9.     procedure SomeProcedure;
  10.   end;
  11.  
  12.   { TSomeObj }
  13.  
  14.   TSomeObj = class( TInterfacedObject, IInterface1, IInterface2 )
  15.     function _AddRef: longint; cdecl;
  16.     function _Release: longint; cdecl;
  17.     procedure SomeProcedure;
  18.   end;
  19.  
  20. var
  21.   IntfVar: IInterface1;
  22.   obj: TSomeObj;
  23.  
  24. { TSomeObj }
  25.  
  26. function TSomeObj._AddRef: longint; cdecl;
  27. begin
  28.   Result:= -1;
  29. end;
  30.  
  31. function TSomeObj._Release: longint; cdecl;
  32. begin
  33.   Result:= -1;
  34. end;
  35.  
  36. procedure TSomeObj.SomeProcedure;
  37. begin
  38.   WriteLn( 'Hello!' );
  39. end;
  40.  
  41. begin
  42.   obj:= TSomeObj.Create;
  43.   IntfVar:= obj;
  44.   if ( IntfVar is IInterface2 ) then
  45.     IInterface2( IntfVar ).SomeProcedure;
  46.   obj.Free;
  47. end.
  48.  
But this gives me a SIGSEV.

Lazarus 1.9 with FPC 3.0.4
Target: Manjaro Linux 64 Bit (4.9.68-1-MANJARO)

mse

  • Sr. Member
  • ****
  • Posts: 253
Re: is and as operators with CORBA interfaces.
« Reply #22 on: December 28, 2017, 10:08:09 am »
Ok but how do I prevent the reference counting in detail?
Do you suggest using TInterfacedPersistent as a base?
Don't do that, it opens a can of worms. One never knows if FPC holds a hidden temporary copy of interface pointers and when it goes out of scope and Release() will be called. It can be that the assigned class instance already has been destroyed at that moment. If you don't need reference counting use CORBA-interfaces not COM. Never combine COM-Interfaces with class instances with normal lifetime handling by create()/destroy().
Quote
So the interface GUID is just a unique string for Corba interfaces?
Correct:
https://www.freepascal.org/docs-html/current/ref/refse47.html#x100-1220007.6
shorter strings which differ in the first characters are more efficient, MSEide generates such strings with RightClick-'Insert UID'.
Quote
What about COM, does it have to be a guid like this? ['{18740D8D-D2E9-4A76-A43D-DFC2057CD2FF}']
Correct, the string will be converted to a TGuid:
https://www.freepascal.org/docs-html/current/ref/refse43.html#x96-1180007.2
Code: Pascal  [Select]
  1. IntfVar is IInterface2
  2.  
with COM actually does
Code: Pascal  [Select]
  1.     function fpc_intf_is(const S: pointer; const iid: TGUID): Boolean;[public,alias: 'FPC_INTF_IS']; compilerproc;
  2.       var
  3.         tmpi: pointer;
  4.       begin
  5.         tmpi:=nil;
  6.         fpc_intf_is:=Assigned(S) and (IUnknown(S).QueryInterface(iid,tmpi)=S_OK);
  7.         if Assigned(tmpi) then
  8.           IUnknown(tmpi)._Release;
  9.       end;
  10.  
so it does not return "true" if the given interface inherits from IInterface2 but if the attached class instance implements exactly IInterface2. I don't know if it does what you need because
Code: Pascal  [Select]
  1. program project1;
  2.  
  3. {$interfaces com}
  4. type
  5.   IInterface1 = interface ['{D6537088-AA99-4656-B88E-615917CF75BB}']
  6.    function getinstance: tobject;
  7.   end;
  8.   IInterface2 = interface ( IInterface1 ) ['{89493813-85C4-4DF7-86BE-3F6CC3978790}']
  9.     procedure SomeProcedure;
  10.   end;
  11.   ttest = class(tinterfacedobject,iinterface1)
  12.    function getinstance(): tobject;
  13.   end;
  14.  
  15.   ttest1 = class(ttest,iinterface2)
  16.    procedure someprocedure();
  17.   end;
  18.  
  19. function ttest.getinstance(): tobject;
  20. begin
  21.  result:= self;
  22. end;
  23.  
  24. procedure ttest1.someprocedure();
  25. begin
  26.  writeln('**someprocedure');
  27. end;
  28.    
  29. var
  30.   IntfVar: IInterface1;
  31.   t1: ttest;
  32. begin
  33.   {Some assignments to IntfVar}
  34.   intfvar:= iinterface1(ttest1.create());
  35.   if ( IntfVar is IInterface2 ) then
  36.     IInterface2( IntfVar ).SomeProcedure;
  37. end.{ ttest }
  38.  
crashes at "    IInterface2( IntfVar ).SomeProcedure;"
It can be done with CORBA:
Code: Pascal  [Select]
  1. program project1;
  2.  
  3. {$interfaces corba}
  4. type
  5.   IInterface1 = interface ['{D6537088-AA99-4656-B88E-615917CF75BB}']
  6.    function getinstance: tobject;
  7.   end;
  8.   IInterface2 = interface ( IInterface1 ) ['{89493813-85C4-4DF7-86BE-3F6CC3978790}']
  9.     procedure SomeProcedure;
  10.   end;
  11.  
  12.   ttest = class(tobject,iinterface1)
  13.    function getinstance(): tobject;
  14.   end;
  15.  
  16.   ttest1 = class(ttest,iinterface2)
  17.    procedure someprocedure();
  18.   end;
  19.  
  20. function ttest.getinstance(): tobject;
  21. begin
  22.  result:= self;
  23. end;
  24.  
  25. procedure ttest1.someprocedure();
  26. begin
  27.  writeln('**someprocedure');
  28. end;
  29.    
  30. var
  31.   IntfVar: IInterface1;
  32.   intfvar2: iinterface2;
  33.   t1: ttest;
  34. begin
  35.   t1:= ttest1.create();
  36.   {Some assignments to IntfVar}
  37.   intfvar:= iinterface1(t1);
  38.   if intfvar.getinstance().getinterface(iinterface2,intfvar2) then begin
  39.    intfvar2.someprocedure();
  40.   end;
  41.   t1.destroy();
  42. end.{ ttest }
  43.  
Or
Code: Pascal  [Select]
  1. program project1;
  2.  
  3. {$interfaces corba}
  4. type
  5.   IInterface1 = interface ['{D6537088-AA99-4656-B88E-615917CF75BB}']
  6.    function GetInterface(const iidstr : shortstring;out obj) : boolean;
  7.   end;
  8.   IInterface2 = interface ( IInterface1 ) ['{89493813-85C4-4DF7-86BE-3F6CC3978790}']
  9.     procedure SomeProcedure;
  10.   end;
  11.  
  12.   ttest = class(tobject,iinterface1)
  13.    function getinstance(): tobject;
  14.   end;
  15.  
  16.   ttest1 = class(ttest,iinterface2)
  17.    procedure someprocedure();
  18.   end;
  19.  
  20. function ttest.getinstance(): tobject;
  21. begin
  22.  result:= self;
  23. end;
  24.  
  25. procedure ttest1.someprocedure();
  26. begin
  27.  writeln('**someprocedure');
  28. end;
  29.    
  30. var
  31.   IntfVar: IInterface1;
  32.   intfvar2: iinterface2;
  33.   t1: ttest;
  34. begin
  35.   t1:= ttest1.create();
  36.   {Some assignments to IntfVar}
  37.   intfvar:= iinterface1(t1);
  38.   if intfvar.getinterface(iinterface2,intfvar2) then begin
  39.    intfvar2.someprocedure();
  40.   end;
  41.   t1.destroy();
  42. end.{ ttest }
  43.  
« Last Edit: December 28, 2017, 10:11:14 am by mse »

PascalDragon

  • Jr. Member
  • **
  • Posts: 77
  • Compiler Developer
Re: is and as operators with CORBA interfaces.
« Reply #23 on: January 02, 2018, 10:52:57 pm »
If I use "is" and "as" operators with CORBA interfaces I get:
Code: Pascal  [Select]
  1. Error: Class or COM interface type expected, but got "IP3DStreamableContainer"
  2. Explanation: Some operators, such as the AS operator, are only applicable to classes or COM interfaces.
Does it mean it does not work with corba? I'm asking because here it is stated differently:
Quote
The as and is operators also work on interfaces (both COM and CORBA). They can be used to check whether an interface also implements another interface as in the following example... https://www.freepascal.org/docs-html/ref/refsu51.html#x154-17600012.8.7

I'm wondering if the error is somewhere else (maybe because of an implicit IUnknown descendance) so it would be good to know if the message or the documentation is at fault.
You need to read the full text as at the bottom of the linked text is this (bold by me):
Quote
Additionally, the is operator can be used to check if a class implements an interface, and the varas operator can be used to typecast an interface back to the class:
{$mode objfpc} 
var 
  i: IMyInterface; 
begin 
  i := TMyObject.Create; 
  Writeln(BoolToStr(i is TMyObject,True)); // prints true 
  Writeln(BoolToStr(i is TObject,True)); // prints true 
  Writeln(BoolToStr(i is TAggregatedObject,True)); // prints false 
  (i as TMyObject).Foo; 
end.

Although the interfaces must be COM interfaces, the typecast back to a class will only work if the interface comes from an Object Pascal class. It will not work on interfaces obtained from the system by COM.
The as and is operators are defined for CORBA (or raw) interfaces only in the direction from the class to the interface. The other way, from the interface to the class, only works for COM interfaces. Additionally the interface needs to have a unique identifier (either a GUID (COM & CORBA/raw) or some other string (CORBA/raw only)).

Thaddy

  • Hero Member
  • *****
  • Posts: 5387
Re: is and as operators with CORBA interfaces.
« Reply #24 on: January 02, 2018, 11:07:45 pm »
Ok {$mode delphi}{$static on} (This may solve it, if you know the correct syntax.....which is in the fm)

Anyway CORBA  interfaces are  a bad idea. Unless you need them. DO NOT EVER USE CORBA INTERFACES LOCALLY IF YOU DO NOT UNDERSTAND INTERFACES.
< I promised not to be grumpy, so in 2018 I will be merely angry  >:( >:( >:(> 8-)

Forget about is and as with CORBA.


Naaahh I'll stick with grumpy...< >:D> Happy New Year 2018
« Last Edit: January 02, 2018, 11:20:58 pm by Thaddy »
High(Methusalem) - 1;

soerensen3

  • Jr. Member
  • **
  • Posts: 64
Re: is and as operators with CORBA interfaces.
« Reply #25 on: January 03, 2018, 12:59:32 am »
Thanks, that helped! I think I will stick to CORBA for now and see if it works better.
Happy New Year!
Lazarus 1.9 with FPC 3.0.4
Target: Manjaro Linux 64 Bit (4.9.68-1-MANJARO)

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus