girona
asked on
Runtime functions/procedures
I need to call a function/procedure at runtime. What I know is the name of the function. I don't want to use a case or if condition to do that. I'm using Delphi 4.
ASKER
I have an editbox and when I write the name of a function in it I want to execute it.
I guess you mean this:
var str : string = 'functionBlaBla';
begin
call(str);
end;
Right?
That doesn't work this way, sorry... :-(
But there are some workarounds. The best one is probably to use a dll, because then you can use GetProcAddress(dllHandle,f unctionStr ).
Perhaps you should tell us more about for which purpose you need that. Then we'll find the best workaround for you...
Regards, Madshi.
var str : string = 'functionBlaBla';
begin
call(str);
end;
Right?
That doesn't work this way, sorry... :-(
But there are some workarounds. The best one is probably to use a dll, because then you can use GetProcAddress(dllHandle,f
Perhaps you should tell us more about for which purpose you need that. Then we'll find the best workaround for you...
Regards, Madshi.
ASKER
I have an editbox and when I write the name of a function in
ASKER
I can't use dll's because do many processes involving other forms and components and it would be a mess right now to move everything into a dll.
Ok, then you should do something like this:
type TGironasProc = procedure (int: integer); // or other parameters...
var procArr : array [0..9] of record
name: string;
proc: TGironasProc;
end;
function CallProc(name: string; param: integer) : boolean;
begin
result:=false;
for i1:=0 to 9 do
if name=procArr[i1].name then begin
result:=true;
procArr[i1].proc(param);
exit;
end;
end;
initialization
procArr[0].name:='example1 '; procArr[0].proc:=example1;
procArr[1].name:=...
...
end.
Of course this method has some disadvantages:
(1) The parameters of the functions must be the same.
(2) You must fill the array.
(3) All the functions of the array are always linked in every program where you're using this unit. The linker can't remove them, because he doesn't know if he may do it...
Regards, Madshi.
type TGironasProc = procedure (int: integer); // or other parameters...
var procArr : array [0..9] of record
name: string;
proc: TGironasProc;
end;
function CallProc(name: string; param: integer) : boolean;
begin
result:=false;
for i1:=0 to 9 do
if name=procArr[i1].name then begin
result:=true;
procArr[i1].proc(param);
exit;
end;
end;
initialization
procArr[0].name:='example1
procArr[1].name:=...
...
end.
Of course this method has some disadvantages:
(1) The parameters of the functions must be the same.
(2) You must fill the array.
(3) All the functions of the array are always linked in every program where you're using this unit. The linker can't remove them, because he doesn't know if he may do it...
Regards, Madshi.
Then I think I've to agree with Madshi, the way of typing in the name of the function doesn't work. Using a list(box) and a case statement are the solutions I would choose for. You have to do the conversion anyway, from the string in the box to the call of the function in the unit.
:O)
:O)
Girona...
Actually you can do it using RTTI info...MethodAddress will return the address of "Published" Methods.
Create a new Component...that will hold all your "Published" procedures and functions....see following example...
Hope this works for you
Rick
unit Unit1;
interface
(*Note ListBox1 has the items filled with the following strings:
MyProcedure1, MyProcedure2, MyProcedure3*)
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TMethodComponent = Class(Tcomponent)
procedure MyProcedure1;
procedure MyProcedure2;
procedure MyProcedure3;
end;
TForm1 = class(TForm)
ListBox1: TListBox;
procedure FormCreate(Sender: TObject);
procedure ListBox1Click(Sender: TObject);
private
{ Private declarations }
FMyMethod : TNotifyEvent;
FMethodComponent: TMethodComponent;
public
{ Public declarations }
procedure MyMethod;
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TMethodComponent.MyProcedu re1;
begin
ShowMessage('My Procedure 1');
end;
procedure TMethodComponent.MyProcedu re2;
begin
ShowMessage('My Procedure 2');
end;
procedure TMethodComponent.MyProcedu re3;
begin
ShowMessage('My Procedure 3');
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FMethodComponent := TMethodComponent.Create(Se lf);
end;
procedure TForm1.MyMethod;
begin
if Assigned(FMyMethod) then
FMyMethod(Self);
end;
procedure TForm1.ListBox1Click(Sende r: TObject);
var
Meth: TMethod;
begin
Meth.Data := FMethodComponent;
Meth.Code := FMethodComponent.MethodAdd ress(ListB ox1.Items[ ListBox1.I temIndex]) ;
FMyMethod := TNotifyEvent(Meth);
MyMethod;
end;
end.
Actually you can do it using RTTI info...MethodAddress will return the address of "Published" Methods.
Create a new Component...that will hold all your "Published" procedures and functions....see following example...
Hope this works for you
Rick
unit Unit1;
interface
(*Note ListBox1 has the items filled with the following strings:
MyProcedure1, MyProcedure2, MyProcedure3*)
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TMethodComponent = Class(Tcomponent)
procedure MyProcedure1;
procedure MyProcedure2;
procedure MyProcedure3;
end;
TForm1 = class(TForm)
ListBox1: TListBox;
procedure FormCreate(Sender: TObject);
procedure ListBox1Click(Sender: TObject);
private
{ Private declarations }
FMyMethod : TNotifyEvent;
FMethodComponent: TMethodComponent;
public
{ Public declarations }
procedure MyMethod;
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TMethodComponent.MyProcedu
begin
ShowMessage('My Procedure 1');
end;
procedure TMethodComponent.MyProcedu
begin
ShowMessage('My Procedure 2');
end;
procedure TMethodComponent.MyProcedu
begin
ShowMessage('My Procedure 3');
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FMethodComponent := TMethodComponent.Create(Se
end;
procedure TForm1.MyMethod;
begin
if Assigned(FMyMethod) then
FMyMethod(Self);
end;
procedure TForm1.ListBox1Click(Sende
var
Meth: TMethod;
begin
Meth.Data := FMethodComponent;
Meth.Code := FMethodComponent.MethodAdd
FMyMethod := TNotifyEvent(Meth);
MyMethod;
end;
end.
Girona...
You can pass function results as follows...If you need to also have procedures...I would suggest that you convert your procedures to functions and pass Null values or empty strings..
Rick
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TMyFunction = function: variant of Object;
TMethodComponent = Class(Tcomponent)
function MyFunction1: variant;
function MyFunction2: variant;
function MyFunction3: variant;
end;
TForm1 = class(TForm)
ListBox1: TListBox;
Label1: TLabel;
procedure FormCreate(Sender: TObject);
procedure ListBox1Click(Sender: TObject);
private
{ Private declarations }
FMyMethod : TMyFunction;
FMyVariant: Variant;
FMethodComponent: TMethodComponent;
public
{ Public declarations }
procedure MyMethod;
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
function TMethodComponent.MyFunctio n1: variant;
begin
ShowMessage('My Function 1');
result := 100.99
end;
function TMethodComponent.MyFunctio n2: variant;
begin
ShowMessage('My Function 2');
result := 'My String';
end;
function TMethodComponent.MyFunctio n3: variant;
begin
ShowMessage('My Function 3');
result := 99
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FMethodComponent := TMethodComponent.Create(Se lf);
end;
procedure TForm1.MyMethod;
begin
if Assigned(FMyMethod) then
FMyVariant := FMyMethod;
end;
procedure TForm1.ListBox1Click(Sende r: TObject);
var
Meth: TMethod;
begin
Meth.Data := FMethodComponent;
Meth.Code := FMethodComponent.MethodAdd ress(ListB ox1.Items[ ListBox1.I temIndex]) ;
FMyMethod := TMyFunction(Meth);
MyMethod;
Label1.Caption := FMyVariant;
end;
You can pass function results as follows...If you need to also have procedures...I would suggest that you convert your procedures to functions and pass Null values or empty strings..
Rick
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TMyFunction = function: variant of Object;
TMethodComponent = Class(Tcomponent)
function MyFunction1: variant;
function MyFunction2: variant;
function MyFunction3: variant;
end;
TForm1 = class(TForm)
ListBox1: TListBox;
Label1: TLabel;
procedure FormCreate(Sender: TObject);
procedure ListBox1Click(Sender: TObject);
private
{ Private declarations }
FMyMethod : TMyFunction;
FMyVariant: Variant;
FMethodComponent: TMethodComponent;
public
{ Public declarations }
procedure MyMethod;
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
function TMethodComponent.MyFunctio
begin
ShowMessage('My Function 1');
result := 100.99
end;
function TMethodComponent.MyFunctio
begin
ShowMessage('My Function 2');
result := 'My String';
end;
function TMethodComponent.MyFunctio
begin
ShowMessage('My Function 3');
result := 99
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FMethodComponent := TMethodComponent.Create(Se
end;
procedure TForm1.MyMethod;
begin
if Assigned(FMyMethod) then
FMyVariant := FMyMethod;
end;
procedure TForm1.ListBox1Click(Sende
var
Meth: TMethod;
begin
Meth.Data := FMethodComponent;
Meth.Code := FMethodComponent.MethodAdd
FMyMethod := TMyFunction(Meth);
MyMethod;
Label1.Caption := FMyVariant;
end;
You can use GetProcAddress using hInstance as the handle of the file where the functions are, rather than opening a DLL and getting a handle to it.
Alex
Alex
Hi Alex,
does that really work? I never tried it, but it sounds like a good idea... :-) Does that work for all functions?
However, different parameters are still a problem, but I think that doesn't matter that much.
Regards, Madshi.
does that really work? I never tried it, but it sounds like a good idea... :-) Does that work for all functions?
However, different parameters are still a problem, but I think that doesn't matter that much.
Regards, Madshi.
Hi Alex,
does that really work? I never tried it, but it sounds like a good idea... :-) Does that work for all functions?
However, different parameters are still a problem, but I think that doesn't matter that much.
Regards, Madshi.
does that really work? I never tried it, but it sounds like a good idea... :-) Does that work for all functions?
However, different parameters are still a problem, but I think that doesn't matter that much.
Regards, Madshi.
ASKER
I want an easier solution, instead of yours I could create a form or do the if solution, but I need a way to call it really easy.
Hi Alex, could you be more specific? please send an example, thanks.
Hi Alex, could you be more specific? please send an example, thanks.
Simplier?
Are you trying not to program?
Rick
Are you trying not to program?
Rick
Hello, Girona...
sorry for taking too long to answer. Gotta work all day long and get ready for Carnival!
You have to export the functions. Make sure all of them use the same number of parameters and parameter types and all in the same sequence. Do it even if you have to make some "dumb" parameters (you know what I mean, right?).
I cannot send you code for that right because there's nothing but Netscape and MS Office in the machie I am an right now.
When I get home you'll do some testing and post the results here.
Yours,
Alex
sorry for taking too long to answer. Gotta work all day long and get ready for Carnival!
You have to export the functions. Make sure all of them use the same number of parameters and parameter types and all in the same sequence. Do it even if you have to make some "dumb" parameters (you know what I mean, right?).
I cannot send you code for that right because there's nothing but Netscape and MS Office in the machie I am an right now.
When I get home you'll do some testing and post the results here.
Yours,
Alex
Happy partying! Alex :O)
ASKER
Thanks Alex,
I'll be waiting any notice from you. I think till then I'll use an 'if' sentence.
I'll be waiting any notice from you. I think till then I'll use an 'if' sentence.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
That works fine, and has good comments. Thanks.
Could you be a bit clearer? Can't figure out what you mean exactly.
You have a function you need to call at runtime, is it under certain conditions or has it to be called by an event?
:O)