• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 169
  • Last Modified:

some sort of procedure pointer...dunno if this is possible though...

Hiya all!

Here's the setup that I've got:

Unit1

func1
func2
func3
funcdo


Unit2

func1
func2
func3



In fact I've got LOADS more functions in unit1 and unit2 but I'd need to make a new post just to list them all :) But only one 'funcdo'. What is currently happening is:

1) a function in unit1 is ran (but not funcdo just yet) and sets a global variable
2) this keeps happening based on what the user does
3) eventually funcdo is called
4) funcdo uses a switch statement and goes through all of the values of the gobal variable that could be assigned to it
5) It then calls the appropriate function in unit2

As I've said I've got LOADS (over 70+) functions in both unit1 and unit2 each. What I'm wanting is for each function in unit1 (not funcdo) to set a pointer or something to the function that would needed to be called in unit2. Then when funcdo is ran it actually calls that function using the pointer. The problem though is that many of the functions don't have the same number or type of arguments as that seems to have been the requirement to do what I want to do.


Can anybody give me a bit of a shove in the right direction? :)

Thanks
NAE
0
nearlyanexpert
Asked:
nearlyanexpert
  • 4
  • 3
1 Solution
 
mocartsCommented:
you can use unit name prefix to explicitly tell compiler which function to call:

Result := unit2.func1(params);

wbr, mo.
0
 
zebadaCommented:
If your functions all have the same return type, you can declare them with an arg list of "array of const" as follows:

You can then use the same "function pointer type" variable to reference any of your 70+ functions.

TGenericFunction = function(vargs: array of const): integer;

...

// These functions are from your unit2
function func2a(vargs: array of const): integer;
begin
  Result := vargs[0].VInteger;
end;

function func2b(vargs: array of const): integer;
begin
  Result := vargs[0].VInteger*vargs[1].VInteger;
end;

This represents your "funcdo" function:
procedure TForm1.Button1Click(Sender: TObject);
var
  fa,fb: TGenericFunction;
begin
  // You would need to decide which function to call and what parameters to pass to it here.
// I've just show an exampole of calling both functions.
  fa := func2a;
  fb := func2b;
  ShowMessage(Format('Func1=%d Func2=%d',[fa([10]),fb([10,20])]));
end;

There may be a more elegant way but this is the only way I know to do it.
If all your functions have the same argument list then you would declare that argument list instead of "array of const".

Regards
Paul
0
 
nearlyanexpertAuthor Commented:
Darn....my fault, its not a function at all I'm needing its a procedure pointer :(. None of the functions in anything return a value...

mocarts, I'm aware of that, although I know what I need to do but just don't know how to do it.

zebada, yeah summit like that, although I got mixed up with function and procedure :(. Although in the,

TGenericFunction = function(vargs: array of const): integer;

What does the ": integer;" mean at the end? Is that the return type or something? What would I put if nothing was returned at all?


Here's how a couple of things are declared:


Unit1

procedure Tfrmmain.btn1Click(Sender: TObject);
begin
   //I want to set some global pointer thingy to the procedure func2 in Unit2
end;

procedure funcdo;
begin
   // run the pointer procedure thingy
end;



Unit2

procedure func2(restriction: String);
begin
   //daft stuff done
end;



Dunno if that has made things better.

NAE
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
nearlyanexpertAuthor Commented:
hmm...I've sorta figured it out, however I want:


TGenericFunction = function(vargs: array of const): integer;

available to just this unit. The things like:


fa,fb: TGenericFunction

I want available also to just unit also, so that when a few buttons are pressed each one is able to set fa to a different procedure, and then when a certain button is pressed the procedure that is assigned to fa is called.

That's it.

Thanks again,
NAE
0
 
nearlyanexpertAuthor Commented:
btw I've tried the following:


(just under the Unit1 public section)

var
  frmmain: Tfrmmain;
    Genprocedure : procedure(Const S: array of Char);
    filter_producer_call : Genprocedure;


But I get a "constant or type identifier expected" error...


NAE
0
 
zebadaCommented:
Here's the "other" unit containing the functions:
unit Unit1;

interface

uses
  SysUtils,Dialogs;

procedure proc1(vargs: array of variant);
procedure proc2(vargs: array of variant);

implementation

procedure proc1(vargs: array of variant);
begin
  ShowMessage(Format('Proc1: arg1=%d',[Integer(vargs[0])]));
end;

procedure proc2(vargs: array of variant);
begin
  ShowMessage(Format('Proc2: arg1=%d arg2=%d',[Integer(vargs[0]),Integer(vargs[1])]));
end;

end.


Here's the main form with 3 buttons:

unit main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TGenericProcedure = procedure(args: array of variant);

  TForm1 = class(TForm)
    btnProc1: TButton;
    btnProc2: TButton;
    btnDoit: TButton;
    procedure btnProc1Click(Sender: TObject);
    procedure btnProc2Click(Sender: TObject);
    procedure btnDoitClick(Sender: TObject);
  private
    { Private declarations }
    proc: TGenericProcedure;
    args: array of variant;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

Uses
  Unit1;

{$R *.dfm}


procedure TForm1.btnProc1Click(Sender: TObject);
begin
  proc := proc1;
  args := VarArrayOf([10]);
end;

procedure TForm1.btnProc2Click(Sender: TObject);
begin
  proc := proc2;
  args := VarArrayOf([10,20]);
end;

procedure TForm1.btnDoitClick(Sender: TObject);
begin
  proc(args);
end;

end.

0
 
zebadaCommented:
You should also change the call to the proc to this:

procedure TForm1.btnDoitClick(Sender: TObject);
begin
  if ( assigned(proc) ) then
    proc(args);
end;

Otherwise if you call proc when proc is nil it will give an memory fault error.

0
 
nearlyanexpertAuthor Commented:
Thank you!


NAE
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now