Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2007-11

{$Interfaces Corba} and TInterfacedObject

57 messages · 12 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Graeme Geldenhuys

Hi,

I previously asked what is the difference between the supported $Interfaces types. eg: Corba vs COM.

From those replies, they are very much the same, except that Corba

interfaces are NOT reference counted.

So what do I use to create interfaces and classes that implement interfaces? Which declaration style do I use? Or doesn't it make a difference?

type
ICommand = interface(IInterface)
vs
ICommand = interface(IUnkown)
vs
ICommand = interface

Now for created classes that implement those interfaces. What base object do I use?

type
TCommandClass = class(TInterfacedObject, ICommand) vs
TCommandClass = class(TSomeCustomNonReferenceCountedClass, ICommand)

I can't imagine that usig Corba style interfaces that I'm allowed to use TInterfacedObject as a based class, because TInterfacedObject implements reference counting. Is there some other base class I'm supposed to use with Corba style interfaces?

Does FPC have a Non-Reference counted base class already? It's quite simple to implement you own, but is stupid if FPC doesn't already have one.

Also, do I have to specify {$Interfaces Corba} in every unit I have, or is it only needed in the using that defines the interface itself? Basically, is that compiler setting unit based or project (global) based. Why I ask, is because {$mode xxx} is unit based, not global across my whole project. So can I mix Reference counted and Non-Reference counted interface styles in the same project?

I found find any help referencing these issues.... The help topics on interfaces and $Interfaces styles are very vague.

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Joao Morais
to Graeme Geldenhuys
Graeme Geldenhuys wrote 7 lines
So what do I use to create interfaces and classes that implement interfaces? Which declaration style do I use? Or doesn't it make a difference? type ICommand = interface(IInterface) vs ICommand = interface(IUnkown)

They are exactly the same ? (D<=5 and D>=6 compatibility)

ICommand = interface

Under $interfaces com, interface = interface(iunknown)

Show quoted text 7 lines
Now for created classes that implement those interfaces. What base object do I use? type TCommandClass = class(TInterfacedObject, ICommand) vs TCommandClass = class(TSomeCustomNonReferenceCountedClass, ICommand)

I am using my own classes that implement _addref, _release and QueryIntf and am very happy with them. I do use refcounting where I want (everywhere btw) and don't destroy the instance where I don't want.

You will want to use TInterfacedObject class if you:

1. Want refcounting;
2. Don't want to destroy the instance if the refcount 0 (the object will raise an exception);
3. Don't need to descend from another class.
4. Will take care with circular references.

Otherwise you will need to create your own class and:

1. implement _addref, _release and QueryIntf if using com interfaces;
2. do nothing if using corba interfaces (I have no idea how an interface is "queried" here).

I can't imagine that usig Corba style interfaces that I'm allowed to use TInterfacedObject as a based class, because TInterfacedObject implements reference counting. Is there some other base class I'm supposed to use with Corba style interfaces?

Any class. Afaik corba interfaces doesn't implement a method ?

Does FPC have a Non-Reference counted base class already? It's quite simple to implement you own, but is stupid if FPC doesn't already have one.

Err... a class doesn't have refcount, just start with TObject or a descendant.

Also, do I have to specify {$Interfaces Corba} in every unit I have, or is it only needed in the using that defines the interface itself?

You need. See eg MSE units.

Basically, is that compiler setting unit based or project (global) based. Why I ask, is because {$mode xxx} is unit based, not global across my whole project. So can I mix Reference counted and Non-Reference counted interface styles in the same project?

Any compiler directive is unit based. The unit where you declared the interface is what will count here.

I found find any help referencing these issues.... The help topics on interfaces and $Interfaces styles are very vague.

Not vague, they was straight to the point imo.

Joao Morais

Reply by email

Graeme Geldenhuys
to Joao Morais
Joao Morais wrote
> ICommand = interface Under $interfaces com, interface = interface(iunknown)

That much I figured, but the question is what does 'interface' default to if Corba style interfaces are used?

1. implement _addref, _release and QueryIntf if using com interfaces; 2. do nothing if using corba interfaces (I have no idea how an interface is "queried" here).

See, this is where the docs can do with some improvement. :) From my bit of testing with Corba style interfaces, you can use the Supports() method which internally uses the QueryInterface() method, so I would imagine you at least need to implement QueryInterface in your own custom interface enabled base class when using Corba style interfaces.

As for _addref() and _release(), it's still a mystery to me. I would imagine I don't need those, but then I have no idea what the base interface looks like for Corba. No documentation mentions wat it is!

Any class. Afaik corba interfaces doesn't implement a method ?

It must, because I can query the interface using Supports().

Show quoted text 6 lines
> Does FPC have a Non-Reference counted base class already? It's quite > simple to implement you own, but is stupid if FPC doesn't already have > one. Err... a class doesn't have refcount, just start with TObject or a descendant.

I meant a class that supports interfaces. TObject doesn't for COM. Again, no idea for CORBA.

You need. See eg MSE units.

MSEgui implements it's own custom TNullInterfacedObject class which isn't reference counted with the usual IUnkown signature. This is my main question. What is the required functions for CORBA? I know the following is required for IUnkown.

  protected
    function QueryInterface(const IID: TGUID; out Obj): longint; stdcall;
    function _AddRef: longint; stdcall;
    function _Release: longint; stdcall;
Not vague, they was straight to the point imo.

Could you then please point me to the correct documentation covering all these questions. I can't seem to find that information anywhere.

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Graeme Geldenhuys
to Joao Morais: They are exactly the same ? (D<=5 and D>=6 compatibility) Under $interfaces com,…
Joao Morais wrote
Any class. Afaik corba interfaces doesn't implement a method ?

OK, I wrote a quick test app. Added {$Interfaces Corba} in each unit just to be save.

I declared two interfaces as follows:

type
  ICommand = interface
  ['{28D72102-D883-41A1-9585-D86B24D9C628}']
    procedure   Execute;
  end;
  ICommandHolder = interface
  ['{695BA6E1-1120-42D4-A2C3-54F98D5CDA46}']
    function    GetCommand: ICommand;
    procedure   SetCommand(ACommand: ICommand);
  end;

I then defined a class implementing ICommand as follows taking your suggestion of using TObject:

  TAddCommand = class(TObject, ICommand)
  private
    FMemo: TfpgMemo;
  public
    constructor Create(AMemo: TfpgMemo); reintroduce;
    procedure   Execute;
  end;

I then wrote the following code to see if I could query for a supported interface.

var
  cmd: ICommand;
  ins: TAddCommand;
begin
  ins := TAddCommand.Create(memName1);
  if Supports(ins, ICommand, cmd) then
  begin
    writeln('It worked');
    cmd.Execute;
  end;
  ins.Free;
end;

Well, the 'It worked' never appears and the cmd.Execute is never fired, so it's still a mystery how CORBA interfaces work. I'll see if Delphi help maybe mentions something.

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Thorsten Engler
to Graeme Geldenhuys
Show quoted text 7 lines
I then wrote the following code to see if I could query for a supported interface. ... Well, the 'It worked' never appears and the cmd.Execute is never fired, so it's still a mystery how CORBA interfaces work. I'll see if Delphi help maybe mentions something.

You can assign from an object to a (non-COM) interface variable:

var
  Obj: TSomeObject;
  Intf: ISomeInterface;
begin
  ...
  Intf := Obj as ISomeInterface;

But once you got a (non-COM) interface you are stuck with it. As there is no "QueryInterface" method available there is no way to get from an interface to another interface implemented by the same object (Or back to the object for that matter).

As for why your call to Supports fails, Supports internally gets Iinterface (if implemented) from the object and then calls QueryInterface to get a reference to the interface you actually asked for. That naturally only works with COM interfaces.

Cheers,
Thorsten

Reply by email

Graeme Geldenhuys
to Thorsten Engler: You can assign from an object to a (non-COM) interface variable: var Obj: TSomeObject;…
Thorsten Engler wrote
to another interface implemented by the same object (Or back to the object for that matter).

I guess to get back to the Obj instance, you could let your ISomething interface implement "function Instance" which returns the Obj instance. That's a old trick used in Delphi code with COM interfaces.

As for why your call to Supports fails, Supports internally gets Iinterface (if implemented) from the object and then calls QueryInterface to get a reference to the interface you actually asked for. That naturally only works with COM interfaces.

Well in that case, shouldn't the compiler give me a error when I use Corba interfaces and try and use the Supports() method. That would be the logical thing wouldn't it, since Supports() would then *never* work with true CORBA interfaces. Don't give the clueless developer false hope. :-)

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Graeme Geldenhuys
to Micha Nelissen: What is the point of defining a GUID for a non-COM interface? Micha
Micha Nelissen wrote 8 lines
> type > ICommand = interface > ['{28D72102-D883-41A1-9585-D86B24D9C628}'] > procedure Execute; > end; What is the point of defining a GUID for a non-COM interface?

Beats me, I thought that might be needed for querying a object for interfaces it supports... As far as CORBA is concerned, I'm just shooting in the dark here... Information on CORBA usage is limited and I can't find any FPC code examples to give me hints. It seems quite useless having the Corba support in FPC, if everything related to Interfaces requires COM methods.

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Graeme Geldenhuys
to Thorsten Engler: You can assign from an object to a (non-COM) interface variable: var Obj: TSomeObject;…
Thorsten Engler wrote 9 lines
You can assign from an object to a (non-COM) interface variable: var Obj: TSomeObject; Intf: ISomeInterface; begin ... Intf := Obj as ISomeInterface;

[ I can't find the message I just sent in my Outbox, so here it is again. ]

I tried what you said and got a @graemeg:command_interface$ ./test An unhandled exception occurred at $080553C1 :
EInvalidCast : Invalid type cast

and the code...

var
  cmd: ICommand;
  holder: ICommandHolder;
  ins: TAddCommand;
begin
  ins := TAddCommand.Create(memName1);
  cmd := ins as ICommand;
  if Assigned(cmd) then
  begin
    writeln('It worked');
    cmd.Execute;
  end;
  ins.Free;
end;

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Sergei Gorelkin
to Graeme Geldenhuys: Beats me, I thought that might be needed for querying a object for interfaces it…
Graeme Geldenhuys wrote 8 lines
Beats me, I thought that might be needed for querying a object for interfaces it supports... As far as CORBA is concerned, I'm just shooting in the dark here... Information on CORBA usage is limited and I can't find any FPC code examples to give me hints. It seems quite useless having the Corba support in FPC, if everything related to Interfaces requires COM methods.

Think of Corba-styled interfaces as about "interfaces without COM glue", not just as about "interfaces without refcounting". To get runtime typecasting features, you have to implement it yourself. OTOH, you are free to implement anything you want.

As for non-refcounted interfaced base class, you may want to use TComponent. Of course, it has some overhead compared with TInterfacedObject, but its features are quite useful in almost every application.

Regards,
Sergei

Reply by email

Vincent Snijders
to Sergei Gorelkin
Sergei Gorelkin wrote 18 lines
Graeme Geldenhuys wrote: > > Beats me, I thought that might be needed for querying a object for > interfaces it supports... As far as CORBA is concerned, I'm just > shooting in the dark here... Information on CORBA usage is limited > and I can't find any FPC code examples to give me hints. It seems > quite useless having the Corba support in FPC, if everything related > to Interfaces requires COM methods. > Think of Corba-styled interfaces as about "interfaces without COM glue", not just as about "interfaces without refcounting". To get runtime typecasting features, you have to implement it yourself. OTOH, you are free to implement anything you want. As for non-refcounted interfaced base class, you may want to use TComponent. Of course, it has some overhead compared with TInterfacedObject, but its features are quite useful in almost every application.

Given:
type
TAddCommand = class(TBaseCommnad, ICommand)
<bla>

   end;
Does the compiler store somewhere that that TAddCommand implements ICommand? I
assume it does the compile time check that TAddCommand implements all ICommands
methods, but is there something similar provided by the compiler (or RTTI) which can
be used to do something like
   ACommnd := TAddCommand.Create;
   if (ACommand is TBaseCommand) then
     writeln('This works');
   if (ACommand.InheritsFrom('TBaseCommand') then
     writeln('This works');
   if (ACommand is ICommand) then
     writeln('I don't know if this works, but I would expect it if you consider
interfaces similar to abstract base classes');
   if (ACommand.Implements(ICommand)) then
     writeln('I don't know if this works, but it is similar to the InheritsFrom case');

Vincent

Reply by email

Graeme Geldenhuys
to Sergei Gorelkin: Think of Corba-styled interfaces as about "interfaces without COM glue", not just as…
Sergei Gorelkin wrote 5 lines
> Think of Corba-styled interfaces as about "interfaces without COM glue", not just as about "interfaces without refcounting". To get runtime typecasting features, you have to implement it yourself. OTOH, you are free to implement anything you want.

So everything I have read up till now about Interfaces are all just based on COM interfaces! I thought seeing that I can't find info in FPC's docs, I would look at Kylix 3 help. Seeing that Kylix is not dependent on COM, in should have a neutral (platfrom independant) interfaces implementation. Yet all the docs in Kylix mentions Supports(), QueryInterface() and TInterfacedObject, so no matter the platform, it seems everything about interfaces are based on Microsoft's COM design. Wow!

Can somebody confirm the following....

I read in a message thread from 2005 that when you use Corba style interfaces, interfaces are also not allowed to inherit from each other. Is this correct?

{$Interfaces Corba}
type
   MyInterfaceA = Interface
     ...
   end;
   MyInterfaceB = Interface(MyInterfaceA)         <===    Not allowed??
    ...
   end;

If the above it true, this is another thing that could be added to the FPC docs. Maybe we should start a "Using Interfaces" chapter in the Programmers Guide or the Language Guide.

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Graeme Geldenhuys
to Graeme Geldenhuys
Graeme Geldenhuys wrote
I read in a message thread from 2005 that when you use Corba style interfaces, interfaces are also not allowed to inherit from each other. Is this correct?

If that is supposed to be true, then we have a problem in FPC 2.2.0 I've just written the following and compiled the unit without any compiler errors.

{$Interfaces Corba}
type
  IntfA = Interface
    function MyFunctionA: integer;
  end;
  IntfB = Interface(IntfA)
    function MyFunctionB: String;
  end;

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Marc Weustink
to Graeme Geldenhuys: I guess to get back to the Obj instance, you could let your ISomething interface…
Graeme Geldenhuys wrote 18 lines
On 29/11/2007, Thorsten Engler wrote: > to another interface implemented by the same object (Or back to the object > for that matter). I guess to get back to the Obj instance, you could let your ISomething interface implement "function Instance" which returns the Obj instance. That's a old trick used in Delphi code with COM interfaces. > As for why your call to Supports fails, Supports internally gets Iinterface > (if implemented) from the object and then calls QueryInterface to get a > reference to the interface you actually asked for. That naturally only works > with COM interfaces. Well in that case, shouldn't the compiler give me a error when I use Corba interfaces and try and use the Supports() method. That would be the logical thing wouldn't it, since Supports() would then *never* work with true CORBA interfaces. Don't give the clueless developer false hope. :-)

Hmm... I reported something similar in the past, which is fixed: http://www.freepascal.org/mantis/view.php?id=6796

(also 6797 and 6798 are somewhat related to this topic)

Marc

Reply by email

Marc Weustink
to Micha Nelissen: What is the point of defining a GUID for a non-COM interface? Micha
Micha Nelissen wrote 8 lines
Graeme Geldenhuys wrote: > type > ICommand = interface > ['{28D72102-D883-41A1-9585-D86B24D9C628}'] > procedure Execute; > end; What is the point of defining a GUID for a non-COM interface?

How would you get a corba interface from a class where this class implements one or more corba interfaces ? They somehow need to be identified.

related to this are:
http://www.freepascal.org/mantis/view.php?id=6797
http://www.freepascal.org/mantis/view.php?id=6798

Marc

Reply by email

Marc Weustink
to Micha Nelissen
Micha Nelissen wrote 6 lines
Marc Weustink wrote: > How would you get a corba interface from a class where this class > implements one or more corba interfaces ? They somehow need to be > identified. AObject as ICorbaInterface ?

And how does the underlying code do the lookup in the interfaces table?

Marc

Reply by email

Graeme Geldenhuys
to Marc Weustink: How would you get a corba interface from a class where this class implements one or more…
Marc Weustink wrote

I can confirm that this doesn't work....

{$Interfaces Corba}
var
  cmd: ICommand;
  holder: ICommandHolder;
  ins: TAddCommand;
begin
  ins := TAddCommand.Create(memName1);
  ins.GetInterface(ICommand, cmd);
  if cmd  nil then
  begin
    writeln('It worked');
    cmd.Execute;
  end;
 ins.free;
end;

"it worked" never gets printed.

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Micha Nelissen
to Marc Weustink: And how does the underlying code do the lookup in the interfaces table? Marc
Marc Weustink wrote 9 lines
Micha Nelissen wrote: > Marc Weustink wrote: >> How would you get a corba interface from a class where this class >> implements one or more corba interfaces ? They somehow need to be >> identified. > > AObject as ICorbaInterface ? And how does the underlying code do the lookup in the interfaces table?

Perhaps it only works if the AObject is a descendent of the class. Or use an interface "vmt" or so? I don't care about it, just like I don't care about how "as TDescendent" works internally.

Mica

Reply by email

Marc Weustink
to Micha Nelissen
Micha Nelissen wrote 12 lines
Marc Weustink wrote: > Micha Nelissen wrote: >> Marc Weustink wrote: >>> How would you get a corba interface from a class where this class >>> implements one or more corba interfaces ? They somehow need to be >>> identified. >> >> AObject as ICorbaInterface ? > > And how does the underlying code do the lookup in the interfaces table? Perhaps it only works if the AObject is a descendent of the class.

Which class ?

Or use an interface "vmt" or so? I don't care about it, just like I don't care about how "as TDescendent" works internally.

I only know that a corba interface needs to be identified somehow otherwise it cant be looked up. (which can't atm)
Be it through GUID, name or vtm.

Anyway I'm not that deep into CORBA, but how do interfacing parties agree on the "type/contract" (or how do you call it) of corba interfaces?

Marc

Reply by email

Marc Weustink
to Graeme Geldenhuys: I can confirm that this doesn't work.... {$Interfaces Corba} var cmd: ICommand; holder:…
Graeme Geldenhuys wrote 26 lines
On 29/11/2007, Marc Weustink wrote: > http://www.freepascal.org/mantis/view.php?id=6798 I can confirm that this doesn't work.... {$Interfaces Corba} var cmd: ICommand; holder: ICommandHolder; ins: TAddCommand; begin ins := TAddCommand.Create(memName1); ins.GetInterface(ICommand, cmd); if cmd nil then begin writeln('It worked'); cmd.Execute; end; ins.free; end; "it worked" never gets printed.

Yes, you cannot query corba objects, since they don't have a QueryInterface method.

However cmd := ins; should work.

Marc

PS.

IMO borland screwed up here when they introduced IInterface = IUnknown. It was IMo cleaner (and you can mix interface types) when they declared it like:

type
   IInterface = interface
   end;
   IUnknown = interface(IInterface)
     _addref...
     _release....
     Query....
   end;

Reply by email

Graeme Geldenhuys
to Marc Weustink: Which class ? I only know that a corba interface needs to be identified somehow otherwise…
Marc Weustink wrote 5 lines
I only know that a corba interface needs to be identified somehow otherwise it cant be looked up. (which can't atm) Be it through GUID, name or vtm.

So based on all these discussions on Corba interfaces, I can only make one conclusion. FPC's Corba interfaces support is not ready yet. So I'll stay with COM based interfaces and remove reference counting if required.

BTW:
I searched the FPC and Lazarus code and couldn't find any TNonRefCountedObject class (or something with a similar name). I have seen many implementations of such a class on the internet and everybody seems to implement it in the same way. Wouldn't it then be a good idea to add such a class into the RTL for convenience. Why must every developer always reinvent the wheel if they want non-reference counted COM interfaces.

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Thorsten Engler
to Marc Weustink: And how does the underlying code do the lookup in the interfaces table? Marc
> AObject as ICorbaInterface ? And how does the underlying code do the lookup in the interfaces table?

There is no "lookup" required for this. An "as" cast from object to interface is only allowed (at least in Delphi) if the compiler can statically at compiletime determine that the type of the AObject variable implements that interface. Objects implement interfaces by having a pointer to the VMT of for the implemented interface in their instance data. So the above cast should get compiled into somethinge like:

If Aobject = nil then
  Intf := nil
Else
  Intf := ICorbaInterface(IntPtr(Aobject) + OffsetOfICorbaInterface);

There is no need for a GUID in this case. (And in Delphi, using an "as" cast like this is the way how you get a reference to an interface that has no GUID.)

It's important to mention here that:

Intf := AObject as ISomeInterface;
and
Supports(Aobject, ISomeInterface, Intf);

Do very different things.

The first one resolves the offset that needs to be applied to AObject to get to ISomeInterface at compiletime based on the type of the variable (not the type of the actual instance which is only known at runtime). The 2nd one uses a call to Aobject.GetInterface, passing in the GUID of Iinterface and then calls QueryInterface with the GUID of ISomeInterface on that.

That can lead to interesting effects:

Type
  TObjectA = class(TInterfacedObject, ISomeInterface)
    procedure SomeMethod; //not virtual!
  end;
  TObjectB = class(TObjectA, ISomeInterface)
    procedure SomeMethod;
  end;
Var
  Obj   : TObjectA;
  IntfA : ISomeInterface;
  IntfB : ISomeInterface;
Begin
  Obj := TObjectB.Create;
  IntfA := Obj as ISomeInterface;
  Supports(Obj, ISomeInterface, IntfB);
  IntfA.SomeMethod; //calls TObjectA.SomeMethod
  IntfB.SomeMethod; //calls TObjectB.SomeMethod
End;

Most of the above assumes you are working with COM style interfaces (the only type of interface supported by Delphi/Kylix which doesn't have any support at compiler level for "CORBA" interfaces).

For "CORBA" interfaces in FPC the only thing that should/can work is casting from an object variable to an interface type using "as" if the compiler can statically at compiletime determine the correct offset to apply to the object pointer to get to the interface VMT and maybe support casting an interface to one of it's parent interfaces. There is no way how "is", "as" or "Supports" could be implemented for such interfacces.

Reply by email

Graeme Geldenhuys
to Marc Weustink: Yes, you cannot query corba objects, since they don't have a QueryInterface method.…
Marc Weustink wrote 10 lines
type IInterface = interface end; IUnknown = interface(IInterface) _addref... _release.... Query.... end;

After all these messages, that does seem like the better solution.

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Graeme Geldenhuys
to Marc Weustink: Yes, you cannot query corba objects, since they don't have a QueryInterface method.…
Marc Weustink wrote
However cmd := ins; should work.

Finally I can get my example code to compile and run correctly! Thanks Marc. I also tried the above where TAddCommand implements two interfaces. It works as well.

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Thorsten Engler
to Marc Weustink: Yes, you cannot query corba objects, since they don't have a QueryInterface method.…
IMO borland screwed up here when they introduced IInterface = IUnknown.

No they didn't.

It was IMo cleaner (and you can mix interface types)

There are no different "types" of interfaces in Delphi/Kylix. Even if there were (like there are in FPC) you can never ever mix them.

Show quoted text 11 lines
when they declared it like: type IInterface = interface end; IUnknown = interface(IInterface) _addref... _release.... Query.... end;

Lets assume we had that definition. Now look at this code:

Var
  Intf : Iinterface;
  Unk  : Iunknown;
Begin
  Unk := //... Get some Iunknown from somewhere
  Intf := Unk; //would be valid as Iunknown derives from Iinterface
               //but as Intf doesn't have an AddRef it can't be called.
  Unk := nil; //Unk has _release which is called and frees the object behind
the interface)
              //Intf now points to a freed object
End;

Beside that, that's the point of such a castrated Iinterface? What can you do with it? No QueryInterface, so you can't get from there to anything else. The as and is operators depend on either methods of Tobject (which can't be reached) or information which is stored at negative offset in the VMT (which isn't present for an interface VMT) so they can't be used either.

Cheers,
Thorsten

Reply by email

Michael Schnell
to Thorsten Engler: There is no "lookup" required for this. An "as" cast from object to interface is only…
An "as" cast from object to interface is only allowed (at least in Delphi) if the compiler can statically at compiletime determine that the type of the AObject variable implements that interface.

Ouups is "as" used differently with interfaces than with objects ? With Objects "as" does a typecast and additionally at runtime looks if the variable's type is (a decedent of) the type given. Otherwise an exception is issued. Am I wrong ?

-Michael

Reply by email

Marc Weustink
to Thorsten Engler: No they didn't. There are no different "types" of interfaces in Delphi/Kylix. Even if…
Thorsten Engler wrote
> IMO borland screwed up here when they introduced IInterface = > IUnknown. No they didn't.

IMO :)

Show quoted text 29 lines
> It was IMo cleaner (and you can mix interface types) There are no different "types" of interfaces in Delphi/Kylix. Even if there were (like there are in FPC) you can never ever mix them. > when they declared it like: > > type > IInterface = interface > end; > > IUnknown = interface(IInterface) > _addref... > _release.... > Query.... > end; Lets assume we had that definition. Now look at this code: Var Intf : Iinterface; Unk : Iunknown; Begin Unk := //... Get some Iunknown from somewhere Intf := Unk; //would be valid as Iunknown derives from Iinterface //but as Intf doesn't have an AddRef it can't be called. Unk := nil; //Unk has _release which is called and frees the object behind the interface) //Intf now points to a freed object End;
True, you need to know what you are doing. It is the same as P:
Pointer; P ;= Unk;

(OK accessing methods is more dificult)

Beside that, that's the point of such a castrated Iinterface? What can you do with it?

The same what you want to do with a CORBA interface ?

No QueryInterface, so you can't get from there to anything else.

You can say the same one you have assigned an object to an interface, no way back to the object. So once you assign a iunkown or object to the stripped iinterface you can only stay there.
If you didn't want that, you shouldn't have used a iinterface in the first place (or cast it as you would have done with a pointer).

The as and is operators depend on either methods of Tobject (which can't be reached) or information which is stored at negative offset in the VMT (which isn't present for an interface VMT) so they can't be used either.

You can do 'is' and 'as' on IUnknown descendants now only too, so no difference.

The only advantage is that you *can* mix reference counted and non reference counted interfaces, where the non reference counted don't require the overhead of an additional exception handler. There are cases I only want the polymorf behaviour of interfaces and not the refercing

Marc

Reply by email

Martin Schreiber
to Graeme Geldenhuys: That much I figured, but the question is what does 'interface' default to if Corba style…
Graeme Geldenhuys wrote 5 lines
> > Also, do I have to specify {$Interfaces Corba} in every unit I have, > > or is it only needed in the using that defines the interface itself? > You need. See eg MSE units.

The {$interfaces corba} in every MSEgui unit is because a FPC bug.

http://www.freepascal.org/mantis/view.php?id=6690

It is fixed now, I will remove the no more needed {$interfaces corba} soon.

Show quoted text 5 lines
MSEgui implements it's own custom TNullInterfacedObject class which isn't reference counted with the usual IUnkown signature. This is my main question. What is the required functions for CORBA? I know the following is required for IUnkown.

tnullinterfacedobject is needed in MSEgui for Delphi compatibility because Delphi has no corba style interfaces.
I think tobject.getinterface should work with corba interfaces too:

http://www.freepascal.org/mantis/view.php?id=6036

MSEgui has a workaround to query corba style interfaces from typeinfo, please use the function getcorbainterface from lib/common/kernel/mseclasses.pas.

Martin

Reply by email

Graeme Geldenhuys
to Martin Schreiber
Martin Schreiber wrote
> tnullinterfacedobject is needed in MSEgui for Delphi compatibility because Delphi has no corba style interfaces.

So basically you want to use interfaces without reference counting. What other benefits did you see to make you decide to use Corba interfaces instead of COM interfaces? Why Corba over COM style? It seems to me the COM interface implementation in FPC is a lot more stable and with more working features.

I'm interested in interfaces, but not interested in reference counting. So I will rather use COM interfaces for now and TNonRefCountingObject (same as TNullInterfacedObject) as my base class to get interface support. I gather that's how MSEgui works under Delphi? Why didn't you do the same under FPC?

I think tobject.getinterface should work with corba interfaces too: http://www.freepascal.org/mantis/view.php?id=6036

It doesn't look like that is going to be fixed any time soon. It was reported in 2005-06-14 and still hasn't even been acknowledged!

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Martin Schreiber
to Graeme Geldenhuys
Graeme Geldenhuys wrote 16 lines
On 30/11/2007, Martin Schreiber wrote: > tnullinterfacedobject is needed in MSEgui for Delphi compatibility > because Delphi has no corba style interfaces. So basically you want to use interfaces without reference counting. What other benefits did you see to make you decide to use Corba interfaces instead of COM interfaces? Why Corba over COM style? It seems to me the COM interface implementation in FPC is a lot more stable and with more working features. I'm interested in interfaces, but not interested in reference counting. So I will rather use COM interfaces for now and TNonRefCountingObject (same as TNullInterfacedObject) as my base class to get interface support. I gather that's how MSEgui works under Delphi? Why didn't you do the same under FPC?

Performance reasons. To use COM interfaces and to ignore reference counting calls in TNonRefCountingObject is no good solution. With the MSEgui getcorbainterface function you can use corba style interfaces until FPC has working getinterface for them.

Show quoted text 7 lines
> I think tobject.getinterface should work with corba interfaces too: > > http://www.freepascal.org/mantis/view.php?id=6036 It doesn't look like that is going to be fixed any time soon. It was reported in 2005-06-14 and still hasn't even been acknowledged!

:-)
Reference counted widestrings is another theme:
http://www.freepascal.org/mantis/view.php?id=6060
And I'd like to remember the 'friend units' where protected class members are accessible in order to avoid the ugly and memory wasting fake class definitions
"
implementation
type
tsomeclass1 = class(tsomeclass)
end;
[....]
with tsomeclass1(someclassinstance) do begin
end;
"
Packages support and faster compiling are on my wishlist too...

Martin

Reply by email

Florian Klaempfl
to Martin Schreiber
>> http://www.freepascal.org/mantis/view.php?id=6036 > It doesn't look like that is going to be fixed any time soon. It was > reported in 2005-06-14 and still hasn't even been acknowledged!

I've no clue how it is supposed to work :)

> :-) Reference counted widestrings is another theme: http://www.freepascal.org/mantis/view.php?id=6060

Mid-term solution will be some unicodestring type, however, it will blow the system unit again that's why I hesitate to implement it.

Show quoted text 12 lines
And I'd like to remember the 'friend units' where protected class members are accessible in order to avoid the ugly and memory wasting fake class definitions " implementation type tsomeclass1 = class(tsomeclass) end; [....] with tsomeclass1(someclassinstance) do begin end; "

This was a bug in 1.0.x-2.0.x violating all OOP rules, this is why it was fixed ;)

Packages support and

This opens a can of worms nobody wants to maintain :)

faster compiling are on my wishlist too...

I don't see a way to improve this, even more, my current machine does a make clean all in 1min20 so I even don't see a need to improve it :)

Reply by email

Florian Klaempfl
to Martin Schreiber: I forgot to mention that the Delphi 'implements' keyword and the interface method…
Show quoted text 8 lines
On Friday 30 November 2007 09.59, Florian Klaempfl wrote: > Martin Schreiber schrieb: >>>> http://www.freepascal.org/mantis/view.php?id=6036 >>> It doesn't look like that is going to be fixed any time soon. It was >>> reported in 2005-06-14 and still hasn't even been acknowledged! > I've no clue how it is supposed to work :) > I forgot to mention that the Delphi 'implements' keyword

FPC supports this? Thought some bugs are known iirc.

and the interface method resolution clauses would be useful too.

What this?

Show quoted text 26 lines
>> :-) >> >> Reference counted widestrings is another theme: >> http://www.freepascal.org/mantis/view.php?id=6060 > Mid-term solution will be some unicodestring type, however, it will blow > the system unit again that's why I hesitate to implement it. > >> And I'd like to remember the 'friend units' where protected class members >> are accessible in order to avoid the ugly and memory wasting fake class >> definitions >> " >> implementation >> type >> tsomeclass1 = class(tsomeclass) >> end; >> [....] >> with tsomeclass1(someclassinstance) do begin >> end; >> " > This was a bug in 1.0.x-2.0.x violating all OOP rules, this is why it > was fixed ;) > You probably misunderstood. I suggest to introduce a new 'uses' like clause where the units with accessible protected class members are listed.

Either you want members to be protected or not ...

Show quoted text 13 lines
Without it and without the "tsomeclass1 = class(tsomeclass)" definitions one ends up with a giant unit file with the whole base functionality of a system, or, even worse, with a bunch of include files. In case of MSEgui it would be about 50'000 lines. >> Packages support and > This opens a can of worms nobody wants to maintain :) > >> faster compiling are on my wishlist too... > I don't see a way to improve this, even more, my current machine does a > make clean all in 1min20 so I even don't see a need to improve it :) Delphi 7 is 10 times faster than FPC 2.2.

Then use D7 or even better TP, it's even faster than D7 ...

8 seconds instead of 1min20 is better, don't you think?

Oh great, please tell me how you accelerated make and process start times.

Reply by email

Graeme Geldenhuys
to Martin Schreiber: I forgot to mention that the Delphi 'implements' keyword and the interface method…
Martin Schreiber wrote
> I forgot to mention that the Delphi 'implements' keyword and the interface method resolution clauses would be useful too.

Aren't those already supported in FPC 2.2.0? I thought 'implements' was around some some time now.

Delphi 7 is 10 times faster than FPC 2.2. 8 seconds instead of 1min20 is better, don't you think?

I'll bite. :-)
What can I compile to do a speed comparison? How do I compile MSEgui under Delphi 7?

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Jonas Maebe
to Martin Schreiber: I forgot to mention that the Delphi 'implements' keyword and the interface method…
Martin Schreiber wrote
Delphi 7 is 10 times faster than FPC 2.2. 8 seconds instead of 1min20 is better, don't you think?

That very much depends on the trade-offs. If there are none: fine. However, if it requires to go back to a compiler design similar to that of 1.0.x (which probably was at least 5 times faster), then 8 seconds would be a lot worse than 1min20. Maintainability, portability and extensibility of the compiler are a lot more important than compilation speed.

Jonas

Reply by email

Graeme Geldenhuys
to Florian Klaempfl: FPC supports this? Thought some bugs are known iirc. What this? Either you want members…
Florian Klaempfl wrote 6 lines
> and the interface > method resolution clauses would be useful too. What this?

I think he means when a class implements a inferfaces and somewhere in the class hierarchy, there already exists a method with the same name. You can then map the Interfaces's methods to new names. Here is a quick example I copied from the net.

TComObject = class(TObject, IUnknown, ISupportErrorInfo)
   protected
   { IUnknown }
   function IUnknown.QueryInterface = ObjQueryInterface;
   function IUnknown._AddRef = ObjAddRef;
   function IUnknown._Release = ObjRelease;

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Florian Klaempfl
to Graeme Geldenhuys
Show quoted text 19 lines
On 30/11/2007, Florian Klaempfl wrote: >> and the interface >> method resolution clauses would be useful too. > What this? > I think he means when a class implements a inferfaces and somewhere in the class hierarchy, there already exists a method with the same name. You can then map the Interfaces's methods to new names. Here is a quick example I copied from the net. TComObject = class(TObject, IUnknown, ISupportErrorInfo) protected { IUnknown } function IUnknown.QueryInterface = ObjQueryInterface; function IUnknown._AddRef = ObjAddRef; function IUnknown._Release = ObjRelease;

This works iirc too?

Reply by email

Martin Schreiber
to Florian Klaempfl: I've no clue how it is supposed to work :) Mid-term solution will be some unicodestring…
Florian Klaempfl wrote 8 lines
Martin Schreiber schrieb: >>> http://www.freepascal.org/mantis/view.php?id=6036 >> >> It doesn't look like that is going to be fixed any time soon. It was >> reported in 2005-06-14 and still hasn't even been acknowledged! I've no clue how it is supposed to work :)

I forgot to mention that the Delphi 'implements' keyword and the interface method resolution clauses would be useful too.

Show quoted text 24 lines
> :-) > > Reference counted widestrings is another theme: > http://www.freepascal.org/mantis/view.php?id=6060 Mid-term solution will be some unicodestring type, however, it will blow the system unit again that's why I hesitate to implement it. > And I'd like to remember the 'friend units' where protected class members > are accessible in order to avoid the ugly and memory wasting fake class > definitions > " > implementation > type > tsomeclass1 = class(tsomeclass) > end; > [....] > with tsomeclass1(someclassinstance) do begin > end; > " This was a bug in 1.0.x-2.0.x violating all OOP rules, this is why it was fixed ;)

You probably misunderstood.
I suggest to introduce a new 'uses' like clause where the units with accessible protected class members are listed.
Without it and without the "tsomeclass1 = class(tsomeclass)" definitions one ends up with a giant unit file with the whole base functionality of a system, or, even worse, with a bunch of include files.
In case of MSEgui it would be about 50'000 lines.

Show quoted text 8 lines
> Packages support and This opens a can of worms nobody wants to maintain :) > faster compiling are on my wishlist too... I don't see a way to improve this, even more, my current machine does a make clean all in 1min20 so I even don't see a need to improve it :)

Delphi 7 is 10 times faster than FPC 2.2.
8 seconds instead of 1min20 is better, don't you think?

Martin

Reply by email

Marco van de Voort
to Martin Schreiber: Is the following from Delphi 7 help possible with FPC? " If the delegate property is of a…

[ Charset ISO-8859-1 unsupported, converting... ]

Show quoted text 6 lines
On Friday 30 November 2007 11.22, Florian Klaempfl wrote: > > I forgot to mention that the Delphi 'implements' keyword > > FPC supports this? Thought some bugs are known iirc. > Is the following from Delphi 7 help possible with FPC?
inttest.pp(13,13) Error: Implements property must have interface type
inttest.pp(17,6) Error: No matching implementation for interface method
"IMyInterface.P2" found
inttest.pp(43) Fatal: There were 2 errors compiling module, stopping

D7 compiles.

Please submit a bug.

Reply by email

Martin Schreiber
to Florian Klaempfl: FPC supports this? Thought some bugs are known iirc. What this? Either you want members…
Florian Klaempfl wrote
> I forgot to mention that the Delphi 'implements' keyword FPC supports this? Thought some bugs are known iirc.

Is the following from Delphi 7 help possible with FPC? "
If the delegate property is of a class type, that class and its ancestors are searched for methods implementing the specified interface before the enclosing class and its ancestors are searched. Thus it is possible to implement some methods in the class specified by the property, and others in the class where the property is declared. Method resolution clauses can be used in the usual way to resolve ambiguities or specify a particular method. An interface cannot be implemented by more than one class-type property. For example,

type
  IMyInterface = interface
    procedure P1;
    procedure P2;
  end;
  TMyImplClass = class
    procedure P1;
    procedure P2;
  end;
  TMyClass = class(TInterfacedObject, IMyInterface)
    FMyImplClass: TMyImplClass;
    property MyImplClass: TMyImplClass read FMyImplClass implements
IMyInterface;
    procedure IMyInterface.P1 = MyP1;
    procedure MyP1;
  end;
procedure TMyImplClass.P1;
  ...
procedure TMyImplClass.P2;
  ...
procedure TMyClass.MyP1;
  ...
var
  MyClass: TMyClass;
  MyInterface: IMyInterface;
begin
  MyClass := TMyClass.Create;
  MyClass.FMyImplClass := TMyImplClass.Create;
  MyInterface := MyClass;
  MyInterface.P1;        // calls TMyClass.MyP1;
  MyInterface.P2;        // calls TImplClass.P2;
end;
"
Show quoted text 5 lines
> and the interface > method resolution clauses would be useful too. What this?

From Delphi 7 Help:
"
You can override the default name-based mappings by including method resolution clauses in a class declaration. When a class implements two or more interfaces that have identically named methods, use method resolution clauses to resolve the naming conflicts.

A method resolution clause has the form

procedure interface.interfaceMethod = implementingMethod;

or

function interface.interfaceMethod = implementingMethod;

where implementingMethod is a method declared in the class or one of its ancestors. The implementingMethod can be a method declared later in the class declaration, but cannot be a private method of an ancestor class declared in another module.

For example, the class declaration

type
  TMemoryManager = class(TInterfacedObject, IMalloc, IErrorInfo)
function IMalloc.Alloc = Allocate;
procedure IMalloc.Free = Deallocate;
    ...
end;

maps IMalloc's Alloc and Free methods onto TMemoryManager's Allocate and Deallocate methods.

A method resolution clause cannot alter a mapping introduced by an ancestor class.
"

Show quoted text 6 lines
> You probably misunderstood. > I suggest to introduce a new 'uses' like clause where the units with > accessible protected class members are listed. Either you want members to be protected or not ...

Or you have a practical tool which is able to solve real world problems...

Martin

Reply by email

Micha Nelissen
to Florian Klaempfl
Florian Klaempfl wrote
Micha Nelissen schrieb: > Well, the best optimization is not needing to do something at all ;-). So you see a way to do make cycle in one compiler call ;)?

Obviously not the three cycles, but maybe one cycle could be done by not compiling the RTL, but by starting to compile the compiler and pass the correct RTL unit/include directories on the commandline so that FPC finds those themselves as needed.

Micha

Reply by email

Florian Klaempfl
to Micha Nelissen
Show quoted text 10 lines
Florian Klaempfl wrote: > Micha Nelissen schrieb: >> Well, the best optimization is not needing to do something at all ;-). > > So you see a way to do make cycle in one compiler call ;)? Obviously not the three cycles, but maybe one cycle could be done by not compiling the RTL, but by starting to compile the compiler and pass the correct RTL unit/include directories on the commandline so that FPC finds those themselves as needed.

Well, problem is that then not all units are build and you don't want to pull in variants etc. into the compiler :)

Reply by email

Florian Klaempfl
to Florian Klaempfl: Well, problem is that then not all units are build and you don't want to pull in variants…
Show quoted text 12 lines
Micha Nelissen schrieb: > Florian Klaempfl wrote: >> Micha Nelissen schrieb: >>> Well, the best optimization is not needing to do something at all ;-). >> So you see a way to do make cycle in one compiler call ;)? > Obviously not the three cycles, but maybe one cycle could be done by not > compiling the RTL, but by starting to compile the compiler and pass the > correct RTL unit/include directories on the commandline so that FPC > finds those themselves as needed. Well, problem is that then not all units are build and you don't want to pull in variants etc. into the compiler :)

OTOH, this might be solved indeed in the future by splitting the rtl. OTOH2, using no build unit but compiling with make -j is faster on multi core systems.

Reply by email

Florian Klaempfl
to Marco van de Voort
Show quoted text 6 lines
> Florian Klaempfl schrieb: > OTOH, this might be solved indeed in the future by splitting the rtl. > OTOH2, using no build unit but compiling with make -j is faster on multi > core systems. Is it? Do you have numbers?

I tested once on Paul Davidson's quad core sparc but I don't remember the numbers.

Reply by email

Marco van de Voort
to Florian Klaempfl: I tested once on Paul Davidson's quad core sparc but I don't remember the numbers.
Show quoted text 10 lines
Marco van de Voort schrieb: >> Florian Klaempfl schrieb: >> OTOH, this might be solved indeed in the future by splitting the rtl. >> OTOH2, using no build unit but compiling with make -j is faster on multi >> core systems. > > Is it? Do you have numbers? I tested once on Paul Davidson's quad core sparc but I don't remember the numbers.

Well, those are not numbers I'm interested in anyway. Sparc doesn't feature binwriter, and 4 cores are (not yet) the norm.

Reply by email

Marco van de Voort
to Jonas Maebe
Show quoted text 8 lines
On 30 Nov 2007, at 15:27, Marco van de Voort wrote: > Well, those are not numbers I'm interested in anyway. Sparc doesn't > feature > binwriter Why would the presence/absence of an integrated assembler make a difference?

Performance is not just CPU, but also disk and startup time. AS influences startup time and CPU (and maybe also Disk when not piped).

With a first of its kind benchmark, I'm a bit hesitant to assume it is similar enough for a binwriter platform.

At least make -j doesn't do any assembling in parallel with the rest when you use an external assembler.

Yes, but the amount of CPU of a single compiler run increases, possibly changing the CPU/Disk balance. So one artificially increases CPU need (AS), and then "shows" that -j remedies that somewhat.

Reply by email

Florian Klaempfl
to Martin Schreiber: http://www.mail-archive.com/fpc-devel%40lists.freepascal.org/msg08029.html Martin
Show quoted text 10 lines
On Friday 30 November 2007 11.23, Graeme Geldenhuys wrote: >> Delphi 7 is 10 times faster than FPC 2.2. >> 8 seconds instead of 1min20 is better, don't you think? > I'll bite. :-) > What can I compile to do a speed comparison? How do I compile MSEgui > under Delphi 7? > http://www.mail-archive.com/fpc-devel%40lists.freepascal.org/msg08029.html

[...]
Compiling printform_mfm.pas
Compiling C:\fpc\mse\lib\common\regcomponents\regunitgroups.pas Linking mseidefp.exe
196091 lines compiled, 7.0 sec, 1783376 bytes code, 905976 bytes data 84 warning(s) issued
69 note(s) issued

Even not enough time to get a gulp of coffee ;)

Reply by email