When a procedural variable is on the left side of an assignment statement, the compiler expects a procedural value on the right. The assignment makes the variable on the left a pointer to the function or procedure indicated on the right. In other contexts, however, using a procedural variable results in a call to the referenced procedure or function. You can even use a procedural variable to pass parameters:
F: function(X: Integer): Integer; I: Integer;
function SomeFunction(X: Integer): Integer;
F := SomeFunction; // assign SomeFunction to F I := F(4); // call function; assign result to I
In assignment statements, the type of the variable on the left determines the interpretation of procedure or method pointers on the right. For example, var
function SomeFunction: Integer;
F := SomeFunction; // assign SomeFunction to F
The first statement assigns a procedural value to f. The second statement copies that value to another variable. The third statement makes a call to the referenced function and assigns the result to I. Because I is an integer variable, not a procedural one, the last assignment actually calls the function (which returns an integer).
In some situations it is less clear how a procedural variable should be interpreted. Consider the statement if F = MyFunction then ...;
In this case, the occurrence of f results in a function call; the compiler calls the function pointed to by f, then calls the function MyFunction, then compares the results. The rule is that whenever a procedural variable occurs within an expression, it represents a call to the referenced procedure or function. In a case where f references a procedure (which doesn't return a value), or where f references a function that requires parameters, the previous statement causes a compilation error. To compare the procedural value of f with MyFunction, use if @F = @MyFunction then ...;
@f converts f into an untyped pointer variable that contains an address, and @MyFunction returns the address of MyFunction.
To get the memory address of a procedural variable (rather than the address stored in it), use @@. For example, @@f returns the address of f.
The @ operator can also be used to assign an untyped pointer value to a procedural variable. For example, var StrComp: function(Str1, Str2: PChar): Integer;
@StrComp := GetProcAddress(KernelHandle, 'lstrcmpi'); calls the GetProcAddress function and points StrComp to the result.
Any procedural variable can hold the value nil, which means that it points to nothing. But attempting to call a nil-valued procedural variable is an error. To test whether a procedural variable is assigned, use the standard function Assigned:
if Assigned(OnClick) then OnClick(X);
Was this article helpful?
What you need to know about… Project Management Made Easy! Project management consists of more than just a large building project and can encompass small projects as well. No matter what the size of your project, you need to have some sort of project management. How you manage your project has everything to do with its outcome.