How to include a method pointer in a typed constant?

I would like to use an object procedure in a record, for example:

TCommandRec = record name: string; fn: procedure of object; end; 

I can create an array with this destination path:

 commands: array [0..1] of TCommandRec; ... commands[0].name := '-help'; commands[0].fn := DoHelp; commands[1].name := '-load'; commands[1].fn := DoLoad; 

I would really like to declare a constant:

 const cmds: array [0..1] of TCommandRec = ( (name: '-help'; fn: DoHelp), (name: '-load'; fn: DoLoad) ); 

However, I get errors for DoHelp and DoLoad - the expected constant expression. These are two class methods. Is there some kind of syntax I need to use to do this work, or am I stuck with creating an array at runtime?

+8
delphi
source share
2 answers

An object method is what is known as two types of pointer. It encapsulates the following information:

  • Function Address
  • The address of the object or object.

The former is known at compile time, but, as a rule, the latter is not. This is why you usually need to create these things at runtime.

If you can agree that an object is known at compile time, you can declare a typed constant for your record type. For example:

 type TMyRecord = record Foo: procedure of object; end; TMyStaticClass = class class procedure Foo; end; class procedure TMyStaticClass.Foo; begin end; const MyRecord: TMyRecord = (Foo: TMyStaticClass.Foo); 

Of course, this will only be useful to you if your functions are viable, like class methods, and not instance methods. I just add the code above to illustrate that you can have constant pointers to methods if the object is a compile-time constant.

+7
source share

You can store pointers to methods in your records (they are known at compile time, so there is no problem defining them in the definition of const):

 TCommandRec = record name: string; fn: Pointer; end; ... const cmds: array [0..1] of TCommandRec = ( (name: '-help'; fn: @DoHelp), (name: '-load'; fn: @DoLoad) ); 

Then, when you need to call fn from cmds[i] (I suppose the call is inside the same class that defines the DoHelp and DoLoad ), write something like:

 type TObjectProc = procedure of object; var m: TMethod; ... m.Code := cmds[i].fn; m.Data := Self; TObjectProc(m); 
+2
source share

All Articles