I am just upgrading some old code written in Delphi 6 to Delphi XE2. Unfortunately the code references a Word97 COM object for generating some .doc documents. There is a direct uses clause of Word97 in the code.
I have to keep the document generated in the same Word format as it is used by an old Crystal Report and another 3rd party app which requries that format of the document.
So, to the question. Because I am using the Word97 in the uses clause, the compiler complains about Types of actual and formal var parameters must be identical whenever an EmptyParam variable is used. This is coming straight out of the Word97.pas source file. This is because EmptyParam is now declared as a function and not a variable.
what is the best way to deal with this? Should I copy the Delphi 6 source files (Word97.pas et al) say into my local directory, directly add them to my project, together with System.Variants.pas and change the Compiler Directive of my app to include EMPTYPARAM_VAR? I haven't tried that, but hopefully it would declare EmptyParam as a variable then. Or perhaps there's an easier solution.
Thanks
EDIT
Here's a little more background info, even though I have accepted an answer, for future reference. Here's an example of the code (AddClaimsLetter is the "Application" COM object - ie TWordApplication):
AddClaimsLetter.Documents.Open(Wordfile, EmptyParam, EmptyParam,
EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
EmptyParam, EmptyParam, EmptyParam, EmptyParam);
Without changing anything, the EmptyParam arguments here failed at compile time stating "E2033 Types of actual and formal var parameters must be identical".
However, because I wanted to keep Word97 (which is in OCX/Server in Delphi 6 Ent. installation folder), I did need to copy the .pas files into my local project file and declare a variable that was used in place of EmptyParam (because these files attempted to compile too and I got the same compiler error as above).
So all working now, but I might discuss with management upgrading to a later version of Office for this App!
Thanks
I quick workaround for the problem might be to declare a local variable of type OleVariant and assign it the result of the function EmptyParam.
For every var
parameter, you should add a local variable that you fill with the EmptyParam
call.
The reason is that all var
parameters are passed by reference. If you pass the same variable at multiple references, you can encounter the following issue (simplified using Integers).
Before: VarParameter=-1
Before: A=-1
Before: B=-1
After: A=2
After: B=2
After: VarParameter=2
EAssertionFailed: Assertion failure
This is the code that shows the risk:
program TheVarParameterRisk;
procedure AssignParameters(var A: Integer; var B: Integer);
begin
Writeln('Before: A=', A);
Writeln('Before: B=', B);
A := 1;
B := 2;
Writeln('After: A=', A);
Writeln('After: B=', B);
Assert(A = 1);
end;
var
VarParameter: Integer;
begin
try
VarParameter := -1;
try
Writeln('Before: VarParameter=', VarParameter);
AssignParameters(VarParameter, VarParameter);
finally
Writeln('After: VarParameter=', VarParameter);
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
You see that in the AssignParameters
the Assert
fails, because the caller passed the same reference into the two var
parameters.
This is exactly the reason that EmptyParam
became a function: it should never be passed as a var
parameter.
People were complaining about bugs in Delphi (for instance here) that caused overwrites of the EmptyParam
value.
That problem is solved now that EmptyParam
is a function. When you need to pass it as a var
parameter, use a local intermediate.
Notes:
EmptyParam
to a var
parameter, then essentially you have problem in itself: a var
parameter means that something is going to be changed, which means that passing EmptyParam
(or a local variable having the same content) is preventing the change.var
parameters in stead of const
parameters), then either the imported type library has the wrong parameter flags, or (if the parameter flags are OK) it is buggy (and you should file a bug report at https://quality.embarcadero.com (this used to be the search engine indexed http://qc.embarcadero.com but that has been shut down; https://quality.embarcadero.com requires a free account to search).Edit:
The fact that you have to pass EmptyParam
in to a var
parameter is a very strong hint into my point that that the function that is called might acually use those parameters and will fail. Just like my example function fails. (Yes, the function documentation might lure you into using multiple EmptyParam
parameters that in fact are not meant to be that empty at all; I've often seen documentation say A and actual functions perform B).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With