Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Execute a procedure known at runtime

1 view
Skip to first unread message

Carlos Saez

unread,
May 14, 2003, 7:52:46 AM5/14/03
to
I need to execute a procedure whose name is known at runtime via a string.
Any idea?
Thanks,
Carlos.

Willo van der Merwe

unread,
May 14, 2003, 7:56:42 AM5/14/03
to
In a DLL? Or a Method?

"Carlos Saez" <carlo...@terra.es> wrote in message
news:3ec22dfe$2...@newsgroups.borland.com...

Carlos Saez

unread,
May 14, 2003, 8:06:10 AM5/14/03
to
Not in a DLL.
It could be a method or a procedure not depending on a object.
The matter is that a procedure in a Unit has to execute another procedure
that is implemented in the same unit or in another one.
Carlos.


"Willo van der Merwe" <wi...@wack.co.za> escribió en el mensaje
news:3ec2...@newsgroups.borland.com...

Willo van der Merwe

unread,
May 14, 2003, 8:37:12 AM5/14/03
to
Remember that Delphi is not an interpreted language such as VisualBasic, PHP
or JavaScript.

You need a way to identify the procedure/method. One way is to use a symbol
table or a hash table where you associate the procedure name with a pointer.
You can do this by building a lookup table yourself or by using RTTI and
have the compiler build the lookup for you.

You also need a way to identify the numer and type of parameters the
procedure might expect and the return type, if it is a function.

The easiest is to identify a fixed number of procedures/methods/functions
you will likely use and define their type like so:

type
T0Function = function : integer; //Function taking 0 parameters and
returning an integer
T0Procedure = procedure; //Procedure taking 0 parameters
TABProcedure = procedure (A,B:integer); //Procedure taking 2 integer
parameters

Then define a constant to identify each type

const
fn0 = 0;
p0 = 1;
pab = 2;

and a type

type
TLookupRec = record
ProcName : string[20]; //function procedure name
ProcType : integer; //function type
ProcPtr : pointer; //function pointer
end;

some functions

function testfn : integer;
begin
Result := 100;
end;

procedure testp;
begin
{do something interresting}
end;

procedure testp2( A, B : integer );
begin
{do something interresting with A and B}
end;

lookup table

var
Lookup = array[0..2] of TLookupRec = (
(ProcName : 'testfn'; ProcType : fn0; ProcPtr : @testfn ),
(ProcName : 'testp'; ProcType : p0; ProcPtr : @testp ),
(ProcName : 'testp2'; ProcType : pab; ProcPtr : @testp2 ) );

the proc to invoke it:

procedure InvokeProc( Name : string );
var
Idx : integer;
begin
Idx := 0;
while Idx < 3 do
begin
if Lookup[Idx].ProcName = Name then
begin
case Lookup[Idx].ProcType of
fn0 : J := T0Function(Lookup[Idx].ProcPtr);
p0 : T0Procedure(Lookup[Idx].ProcPtr);
pab : TABProcedure(Lookup[Idx].ProcPtr)( A, B );
end;
end;
end;
end;

Hope this helps,

Willo

"Carlos Saez" <carlo...@terra.es> wrote in message

news:3ec23122$1...@newsgroups.borland.com...

Jason

unread,
May 14, 2003, 9:40:00 AM5/14/03
to

"Carlos Saez" <carlo...@terra.es> wrote in message
news:3ec22dfe$2...@newsgroups.borland.com...

procedure CommandLine;
Var
i : Integer;
begin
for i := 1 to ParamCount do
begin
if LowerCase(ParamStr(i)) = '-u' then
RunProcedure1;
if LowerCase(ParamStr(i)) = '-p' then
RunProcedure2;
end;
end;

Peter Thönell

unread,
May 14, 2003, 11:06:43 PM5/14/03
to

If all the procedures have the same definition, then you could register the
procedures with an object you make yourself.

eg. (Untested)
TStringList will not work for methods, as you'll need something that can
hold pairs of pointers.

type
TMyProc = procedure ....;

TProcedures = class
private
fProcs: TStringList;
public
procedure Register(ProcName: string; Proc: TMyProc);
procedure Call(ProcName: string; ...parameters... );
end;

var
Procedures : TProcedures ;

procedure TProcedures.Register(ProcName: string; Proc: TMyProc);
begin
fProcs.AddObject( ProcName, TObject(Proc) );
end;

procedure TProcedures.Call(ProcName: string; ...parameters... );
var
i : integer;
begin
i := IndexOf( ProcName )
TMyProc( fProcs.Objects[i] )(...parameters...);
end;

Something along this line is what I would generally do.


Michael Johnson - Father

unread,
May 15, 2003, 8:02:43 AM5/15/03
to

We'll... I've posted this before, and I'll post it again. The following code is experimental, but seems to work for *simple* procedures, it allows you to build an array of parameters on the fly and "invoke" the procedure. Many thanks to Carlo Kok's work in Innerfuse Pascal script.

The only major downfall on this code was pushing floating numbers... if you do, stick with the "Extended" type and cast as needed... I *May* have workaround code laying around here, but it wasn't important to what I was doing, so I quit working on it.

SO, whenever someone tells you something isn't possible, tell them that *EVERYTHING* is possible if you think about it enough.

http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&threadm=3c98a815%241_1%40dnews&rnum=2&prev=/groups%3Fhl%3Den%26lr%3D%26ie%3DUTF-8%26oe%3DUTF-8%26scoring%3Dd%26q%3Dbigattichouse%2BInvoke

tinyURL:

http://tinyurl.com/btja

Mike Johnson
www.bigattichouse.com


Mike Johnson

unread,
May 15, 2003, 8:16:16 AM5/15/03
to

Another, less-likely to explode, method would be to create "Execution objects" that handle each specific function type...

(is psuedo-code:)
TExecutionObject
Parameters[]:Variant or something like that
Execute / virtual;overload;
Execute:Variant / virtual;overload

Even better all the params and result types could be TField.

Now.. for each Type of procedure you wish to execute, you create an Execution Object..

TNotifyEventExecution=class(TExecutionObject)
property Event:TNotifyEvent
execute;override;

This can then call the assigne event.

You could build something like:

MyEventList.CreateExecutionObject (Button1.onclick,TNotifyEvent)

and later call it ...


let me know if you'd like help putting this together.

Oh, and you *CAN* get event types, I just have to remember how to find the info. (RTTI holds it, If my quickrtti project revealed)

Mike
www.bigattichouse.com

Carlos Saez

unread,
May 17, 2003, 6:27:46 AM5/17/03
to
Thank you all for your advice and support.

I'll keep the procedure information in a list (in my case almost every unit
with a form adds a procedure to be call dinamycally, so all of them will be
added to the list in the Initialitation section of each respective unit).
As Michael Jhonson states, I also need to load packages dinamically and
execute procedures inside them (for showing and managing forms).
Although my need for passing parameters to the procedures are much more
simple, I won't forget the method proposed by MJ.
Regards,
Carlos.


"Carlos Saez" <carlo...@terra.es> escribió en el mensaje
news:3ec22dfe$2...@newsgroups.borland.com...

0 new messages