Pass-trough function with array of TVarRec
Hi,
I need to create pass-through function for function with signature ():
function CallIntegerFunction(aValue1: string; aValue2: string; aParams:
array of const): integer;
Is it possible? I don't know how to work with the last parametr of this
function.
Petr Slipek
slipek.at.dosli.cz
I need to create pass-through function for function with signature ():
function CallIntegerFunction(aValue1: string; aValue2: string; aParams:
array of const): integer;
Is it possible? I don't know how to work with the last parametr of this
function.
Petr Slipek
slipek.at.dosli.cz
This discussion has been closed.
Comments
use a 'TStringList' or a 'TList' as ("open array") parameter.
HTH,
Chris Ueberall;
I tried your sugesstion and it works with one exception. I created class
TdoExecuteStringFunction as described in help with TStringList parametr.
When I preview the report - code executes OK. But if I run end-user report
designer and preview report in the report designer the execution of
pass-throught function failed with acess violation at line marked with
"!!!!!" in the code below.
In RAP I assign code to events OnCreate, OnDestroy and Variable1OnCalc;
Now I really don't understand what's going on.
Petr Slipek
Dosli
*************START RAP CODE****************
global var
glParams: TStirngList;
procedure GlobalOnCreate;
begin
glParams := TStringList.Create;
end;
procedure GlobalOnDestroy;
begin
glParams.Free;
glParams := nil;
end;
procedure Variable1OnCalc(var Value: Variant);
begin
glParams.Clear;
glParams.Add(doWeldBase_sznKGroups['TypKurzuCustID']);
Value := ExecuteStringFunction('doWeldBase', 'KurzTypName', glParams);
end;
*************START INTERFACE***************
TdoSystemFunction = class (TraSystemFunction)
public
class function Category: string; override;
end;
TdoExecuteStringFunction = class (TdoSystemFunction)
public
procedure ExecuteFunction(aParams: TraParamList); override;
class function GetSignature: string; override;
class function HasParams: Boolean; override;
end;
*************START IMPLEMENTATION***************
procedure TdoExecuteStringFunction.ExecuteFunction(aParams: TraParamList);
var
lModuleName: string;
lFunctionName: string;
lParams: TStringList;
lArray: array of TVarRec;
I: Integer;
lVarRec: TVarRec;
lResult: string;
begin
lResult := '';
if Assigned(doAppServices) then
begin
GetParamValue(0, lModuleName);
GetParamValue(1, lFunctionName);
GetParamValue(2, lParams);
if (lModuleName = '') or (lFunctionName = '') or (not Assigned(lParams))
then
Exit;
!!!!! SetLength(lArray, lParams.Count);
for I := 0 to lParams.Count - 1 do
begin
lVarRec.VType := vtPChar;
lVarRec.VPChar := PChar(lParams[I]);
lArray[I] := lVarRec;
end;
try
lResult := doAppServices.CallStringFunction(nil, lModuleName,
lFunctionName, lArray);
except
on Exception do lResult := '';
end;
end;
SetParamValue(3, lResult);
end;
class function TdoExecuteStringFunction.GetSignature: string;
begin
result := 'function ExecuteStringFunction(aModuleName: string;
aFunctionName: string; aParams: TStringList): string;';
end;
class function TdoExecuteStringFunction.HasParams: Boolean;
begin
result := True;
end;
****************END
"Chris Ueberall [TeamDM]" p??e v diskusn?m
I forgot to write that it failed only on the first attempt to show preview.
Second time is all ok.
Petr Slipek
Dosli
it helps.
If I modified rap code for Variable1:
*********** START RAP************
procedure Variable1OnCalc(var Value: Variant);
begin
glParams.Clear;
glParams.Add(doWeldBase_sznKGroups['TypKurzuCustID']);
ShowMessage('Mess1: Inside RAP before Execute');
Value := ExecuteStringFunction('doWeldBase', 'KurzTypName', glParams);
end;
***********END RAP************
and modified procedure TdoExecuteStringFunction.ExecuteFunction(aParams:
TraParamList);
**********START IMPLEMENTATION********
procedure TdoExecuteStringFunction.ExecuteFunction(aParams: TraParamList);
var
...
begin
ShowMessage('Mess2: Inside Delphi RAP execution');
lResult := '';
....
end;
*********EDN IMPLEMENTATION************
When the error doesn't occur, the sequence of messages is: Mess1 --> Mess2
as expected,
but when I preview report in end-user designer while running application the
first showed message is Mess2 and next the params are invalid and causes
access violation exception.
Please help. It looks like something called
TdoExecuteStringFunction.ExecuteFunction without running my RAP code.
Thanks,
Petr Slipek
Dosli
I tested your pass-through function without any AV!
Message1 was always shown before Message2.
I would place additional messages for 'Create' and 'Destroy' of the stringlist.
Use a new report.
HTH,
Chris Ueberall;
I tried, but it shows correctly. Another thing is, that I have ppViewer,
ppReport, ppDesigner on one form. Before calling ppDesigner.ShowModal i
preview report in ppViewer. Can it be in conflict with preview panel in
designer? Strange is that it only happens in designer preview panel. Never
in ppViewer.
Petr Slipek
Dosli
"Chris Ueberall [TeamDM]" p??e v diskusn?m
sorry, but I have no idea what causes the AV on your side. If I pass nil the functions returns immediately as it should.
You tested with a new report so there should be no other call before the stringlist is created. Any infos from the call stack available?
I used the standard previewer and the designer preview.
I tried new empty report and it doesn't help. I used CodeSite to see what is
happening. I modified RAP code to:
****START
procedure Variable1OnCalc();
var
glParams: TStringList;
begin
csEnterMethod('Variable1OnCalc');
glParams := TStringList.Create;
csSendMsg('After Creating glParams');
glParams.Clear;
csSendMsg('After Clearing glParams');
glParams.Add('0');
csSendMsg('After Adding glParams');
csSendInteger('before ExecuteStringFunction is glParams.Count in RAP = ',
glParams.Count);
Value := ExecuteStringFunction('doWeldBase', 'TypKurzuNazev', glParams);
csSendInteger('after ExecuteStringFunction is glParams.Count in RAP = ',
glParams.Count);
csSendMsg('Before Freeing glParams');
glParams.Free;
csSendMsg('After Freeing glParams');
csExitMethod('Variable1OnCalc');
end;
****END
and modified delphi code to:
****START
.....
CodeSite.SendInteger('before execute lParams.Count', lParams.Count);
lResult := doAppServices.CallStringFunction(nil, lModuleName,
lFunctionName, lArray);
CodeSite.SendInteger('after execute lParams.Count', lParams.Count);
....
****END
After runnig report I received this sequence of messages
****START
->Variable1OnCalc
After Creating glParams
After Clearing glParams
After Adding Item to glParams
before ExecuteStringFunction is glParams.Count in RAP = 1
-> TdoExecuteStringFunction.ExecuteFunction
before execute Delphi call is lParams.Count = 1
after execute Delphi call is lParams.Count = 1
<- TdoExecuteStringFunction.ExecuteFunction
after ExecuteStringFunction is glParams.Count in RAP = 1
Before Freeing glParams
After Freeing glParams
<-Variable1OnCalc
->Variable1OnCalc
After Creating glParams
After Clearing glParams
After Adding Item to glParams
before ExecuteStringFunction is glParams.Count in RAP = 1
-> TdoExecuteStringFunction.ExecuteFunction
before execute Delphi call is lParams.Count = 0
// look at this line - why 0 - it should be 1
after execute Delphi call is lParams.Count = 0
<- TdoExecuteStringFunction.ExecuteFunction
after ExecuteStringFunction is glParams.Count in RAP = 0
Before Freeing glParams
*******STOP
Calling glParams.Free in RAP, in second runnig causes AV. I don't have
source to rap to see, why lParams.Count in secon run is 0 in Delphi code
altought in RAP is 1.
Petr Slipek
Dosli
P.S. Inside ExecuteFunction is call stack empty. - no source for RAP.
"Chris Ueberall [TeamDM]" <Ueberall@NOSPAM.osd.de> p??e v diskusn?m
glParams[0] before execute pass-through function and for logging lParams[0]
in Delphi ExecuteFunction. And as you can see, delphi function always
receiving older reverence to glParams. Look at the log.
->Variable1OnCalc
After Creating glParams
After Clearing glParams
glParams[0] = 0
before ExecuteStringFunction is glParams.Count in RAP = = 1
->TdoExecuteStringFunction.ExecuteFunction
lParams[0] = '0'
before execute lParams.Count = 1
after execute lParams.Count = 1
<-TdoExecuteStringFunction.ExecuteFunction
after ExecuteStringFunction is glParams.Count in RAP = = 1
Before Freeing glParams
After Freeing glParams
<-Variable1OnCalc
->Variable1OnCalc
After Creating glParams
After Clearing glParams
glParams[0] = 3
before ExecuteStringFunction is glParams.Count in RAP = = 1
->TdoExecuteStringFunction.ExecuteFunction
lParams[0] = '0' <====== should be 3
before execute lParams.Count = 1
after execute lParams.Count = 1
<-TdoExecuteStringFunction.ExecuteFunction
after ExecuteStringFunction is glParams.Count in RAP = = 1
Before Freeing glParams
After Freeing glParams
<-Variable1OnCalc
Petr Slipek
Dosli
The RAP global OnCreate and OnDestroy are going to fire differently when
you preview from the ReportDesigner than when you preview from the
preview form. There is going to be a difference in timing.
If you would like to create a simple example report using DBDemos and
RAP, and send to support@digital-metaphors.com, we can check it out
here.
Best regards,
Nard Moseley
Digital Metaphors
www.digital-metaphors.com
Petr Slipek
Dosli
"Nard Moseley (Digital Metaphors)" p?se v