Sign in Join

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

Mailing lists / fpc-pascal / 2012-07

Dynamic messaging in Delphi

9 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

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

Ryan Joseph

I was asking on the Mac Pascal list if Delphi had any ways to invoke methods on objects which the class was unknown at compile time (like a class that invokes a user defined delegate commonly used in Cocoa Mac programming and I assume Delphi not knowing) and one user told me interfaces will work for this. Btw, I'm aware you can use strings to invoke methods with a single argument but I wanted something better since this has been a real drawback in Pascal for me in recent years.

The idea is Main.pas has a delegate class which implements IMyInterface and MyInterface.pas declares the interface and can invoke its methods using a generic delegate object (typed TObject). This is really typical of UI elements like a button that wants to tell a receiver an action occurred but doesn't know the class of the receiving object. Providing this example works it's sort of a workaround to multiple inheritence but I don't see that Pascal would be capable of this, i.e. simply type casting an object and forcing it to call a method that may or may not exist (I feel like I tried this before and got crashing).

He swears this works and no one else answered otherwise but I'm getting "Error: Class or Object types "TObject" and "IMyInterface" are not related" errors at the line shown below.

Any ideas? Thanks.

====================

{$mode delphi}
{$interfaces corba}
unit MyInterface;
interface
type
	IMyInterface = interface
		procedure DoThis (value: integer);
	end;
procedure InvokeDelegate (delegate: TObject);
implementation
procedure InvokeDelegate (delegate: TObject);
var
	intfDelegate: IMyInterface;
begin
	ERROR ====> intfDelegate := IMyInterface(delegate);
	intfDelegate.DoThis(1);
end;
end.

====================

{$mode delphi}
{$interfaces corba}
program Main;
uses
	MyInterface;
type
	TMyDelegate = class (TInterfacedObject, IMyDelegate)
		procedure DoThis (value: integer);
	end;
procedure TMyDelegate.DoThis (value: integer);
begin
	writeln('did this ', value);
end;
var
	delegate: TMyDelegate;
begin
	delegate := TMyDelegate.Create;
	TestDelegate(delegate);
end.

Regards,
Ryan Joseph
thealchemistguild.com

Luiz Americo Pereira Camara
to Ryan Joseph
Ryan Joseph wrote 5 lines
I was asking on the Mac Pascal list if Delphi had any ways to invoke methods on objects which the class was unknown at compile time (like a class that invokes a user defined delegate commonly used in Cocoa Mac programming and I assume Delphi not knowing) and one user told me interfaces will work for this. Btw, I'm aware you can use strings to invoke methods with a single argument but I wanted something better since this has been a real drawback in Pascal for me in recent years. The idea is Main.pas has a delegate class which implements IMyInterface and MyInterface.pas declares the interface and can invoke its methods using a generic delegate object (typed TObject). This is really typical of UI elements like a button that wants to tell a receiver an action occurred but doesn't know the class of the receiving object. Providing this example works it's sort of a workaround to multiple inheritence but I don't see that Pascal would be capable of this, i.e. simply type casting an object and forcing it to call a method that may or may not exist (I feel like I tried this before and got crashing). He swears this works and no one else answered otherwise but I'm getting "Error: Class or Object types "TObject" and "IMyInterface" are not related" errors at the line shown below.
   if delegate.GetInterface(IMyInterface, intfDelegate) then
     intfDelegate.DoThis

Luiz

Show quoted text 63 lines
Any ideas? Thanks. ==================== {$mode delphi} {$interfaces corba} unit MyInterface; interface type IMyInterface = interface procedure DoThis (value: integer); end; procedure InvokeDelegate (delegate: TObject); implementation procedure InvokeDelegate (delegate: TObject); var intfDelegate: IMyInterface; begin ERROR ====> intfDelegate := IMyInterface(delegate); intfDelegate.DoThis(1); end; end. ==================== {$mode delphi} {$interfaces corba} program Main; uses MyInterface; type TMyDelegate = class (TInterfacedObject, IMyDelegate) procedure DoThis (value: integer); end; procedure TMyDelegate.DoThis (value: integer); begin writeln('did this ', value); end; var delegate: TMyDelegate; begin delegate := TMyDelegate.Create; TestDelegate(delegate); end. Regards, Ryan Joseph thealchemistguild.com _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Ryan Joseph
to Luiz Americo Pereira Camara

I never heard of this syntax, is it Delphi only?

Trying this I got "Error: Interface type IMyInterface has no valid GUID". What else do I need to do?

Thanks.

Luiz Americo Pereira Camara wrote
if delegate.GetInterface(IMyInterface, intfDelegate) then intfDelegate.DoThis

Regards,
Ryan Joseph
thealchemistguild.com

Luiz Americo Pereira Camara
to Ryan Joseph
Ryan Joseph wrote
I never heard of this syntax, is it Delphi only? Trying this I got "Error: Interface type IMyInterface has no valid GUID". What else do I need to do?

The sintaxe i posted is for COM interfaces.

For CORBA interfaces do
   IMyInterface = interface
    ['myintf']
         procedure DoThis (value: integer);
     end;
if delegate.GetInterface('myintf', intfDelegate) then
    intfDelegate.DoThis

Luiz

Show quoted text 17 lines
Thanks. On Jul 24, 2012, at 4:26 PM, Luiz Americo Pereira Camara wrote: > if delegate.GetInterface(IMyInterface, intfDelegate) then > intfDelegate.DoThis Regards, Ryan Joseph thealchemistguild.com <http://thealchemistguild.com> _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Ryan Joseph
to Luiz Americo Pereira Camara

Now it works! That seems redundant to declare an identifier when the interface name itself is unique. I would think the CORBA style identifier should default to the name of the interface.

Thanks, I wanted this feature for a while now.

Luiz Americo Pereira Camara wrote 9 lines
For CORBA interfaces do IMyInterface = interface ['myintf'] procedure DoThis (value: integer); end; if delegate.GetInterface('myintf', intfDelegate) then intfDelegate.DoThis

Regards,
Ryan Joseph
thealchemistguild.com

Graeme Geldenhuys
to Ryan Joseph: I was asking on the Mac Pascal list if Delphi had any ways to invoke methods on objects…
Ryan Joseph wrote 7 lines
procedure InvokeDelegate (delegate: TObject); var intfDelegate: IMyInterface; begin ERROR ====> intfDelegate := IMyInterface(delegate); intfDelegate.DoThis(1); end;

You could also try the Supports() method. eg:

   if Supports(delegate, IMyInterface, intfDelegate) then
     intfDelegate.DoThis(1);
Show quoted text 12 lines
{$mode delphi} {$interfaces corba} program Main; uses MyInterface; type TMyDelegate = class (TInterfacedObject, IMyDelegate) procedure DoThis (value: integer); end;

By the way, as far as I know TInterfacedObject is a COM Interface class only. You are telling the compiler that you want to use CORBA style interfaces, which don't support IUnknown, thus you shouldn't (can't) use TInterfaceObject which implements IUnknown.

Change that class definition to something like the following if you are using CORBA interfaces.

   TMyDelegate = class(TObject, MyDelegate)
      ...
   end;

And that should work correctly with CORBA style interfaces (which don't have reference counting built-in).

Regards, - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://fpgui.sourceforge.net
Ryan Joseph
to Graeme Geldenhuys
Graeme Geldenhuys wrote 5 lines
You could also try the Supports() method. eg: if Supports(delegate, IMyInterface, intfDelegate) then intfDelegate.DoThis(1);

I'm getting an identifier not found error with the procedure "Supports". Where is this defined?

Show quoted text 15 lines
By the way, as far as I know TInterfacedObject is a COM Interface class only. You are telling the compiler that you want to use CORBA style interfaces, which don't support IUnknown, thus you shouldn't (can't) use TInterfaceObject which implements IUnknown. Change that class definition to something like the following if you are using CORBA interfaces. TMyDelegate = class(TObject, MyDelegate) ... end; And that should work correctly with CORBA style interfaces (which don't have reference counting built-in).

That was useless code, you're right, thanks.

Regards,
Ryan Joseph
thealchemistguild.com

Ryan Joseph
to Ludo Brands

Great, I got this working now.

This is one small step better because the only string identifier used in code for the interface is in the declaration itself so if the name of the interface gets changed I'll get compiler warnings when I try to invoke it.

Thanks.

Ludo Brands wrote
http://www.freepascal.org/docs-html/rtl/sysutils/supports.html > I'm getting an identifier not found error with the procedure > "Supports". Where is this defined?

Regards,
Ryan Joseph
thealchemistguild.com