next up previous contents index search.gif
Next: 4. Objects Up: 3. Types Previous: 3.4 Pointers

3.5 Procedural types

Free Pascal has support for procedural types, although it differs a little from the Turbo Pascal implementation of them. The type declaration remains the same, as can be seen in the following syntax diagram:

Procedural types

\begin{syntdiag}\setlength {\sdmidskip}{.5em}\sffamily\sloppy \synt{procedural\ ...
...egin{displaymath}\lit* ; \synt{call\ modifiers} \end{displaymath} \end{syntdiag}

\begin{syntdiag}\setlength {\sdmidskip}{.5em}\sffamily\sloppy \synt{function\ he...
...unction} \synt{formal\ parameter\ list}
\lit*: \synt{result\ type}\end{syntdiag}

\begin{syntdiag}\setlength {\sdmidskip}{.5em}\sffamily\sloppy \synt{procedure\ header} \lit*{procedure} \synt{formal\ parameter\ list}\end{syntdiag}

\begin{syntdiag}\setlength {\sdmidskip}{.5em}\sffamily\sloppy \synt{call\ modifi...
...cdecl} \\
\lit*{pascal} \\
\lit*{stdcall} \\
\lit*{popstack}
\)\end{syntdiag}
For a description of formal parameter lists, see chapter Procedures. The two following examples are valid type declarations:

Type TOneArg = Procedure (Var X : integer);
     TNoArg = Function : Real;
var proc : TOneArg;
    func : TNoArg;
One can assign the following values to a procedural type variable:
  1. Nil, for both normal procedure pointers and method pointers.
  2. A variable reference of a procedural type, i.e. another variable of the same type.
  3. A global procedure or function address, with matching function or procedure header and calling convention.
  4. A method address.
Given these declarations, the following assignments are valid:

Procedure printit (Var X : Integer);
begin
  WriteLn (x);
end;
...
P := @printit;
Func := @Pi;
From this example, the difference with Turbo Pascal is clear: In Turbo Pascal it isn't necessary to use the address operator (@) when assigning a procedural type variable, whereas in Free Pascal it is required (unless you use the -So switch, in which case you can drop the address operator.) Remark that the modifiers concerning the calling conventions (cdecl, pascal, stdcall and popstack stick to the declaration; i.e. the following code would give an error:

Type TOneArgCcall = Procedure (Var X : integer);cdecl;
var proc : TOneArgCcall;
Procedure printit (Var X : Integer);
begin
  WriteLn (x);
end;
begin
P := @printit;
end.
Because the TOneArgCcall type is a procedure that uses the cdecl calling convention. At the moment, the method procedural pointers (i.e. pointers that point to methods of objects, distinguished by the of object keywords in the declaration) are still in an experimental stage.

root
1999-06-10