Tips on using arrays of procedures, and arrays of functions. Arrays of procedures and functions may seem bizarre to you. But they do come useful in some very important situations in advanced software programming. One area where they can be used is plug-in based software. Imagine that you have to import 40 different initialization procedures for 40 different plug-ins that are going to be loaded on the fly. Using setlength, you don't even have to know ahead of time that you have 40 different plug-ins in your /program/extras/plugin/ directory.
If each of your 40 plug-ins have all the same style of initilization procedures, each procedure is going to have the same syntax. So using an array of the procedure offers you access to the same style of procedures, but each procedure internal code being a bit different. Each plug in may have his own inititialization procedure.. not all plug in's want to fire off the same initialization code.
The real power of array's of functions and procedures are the fact that:
-you can access them all at once in a loop
-you can keep track of how many procedures by finding the length of your array
-you can dynamically import or create more functions by using setlength, without
worrying about any limits. You couldn't do this with fixed single procedures.
-if using arrays of procedures/functions in a plug-in system, no multiple calls to
GetProcAddress (GetProcAddr) are required to address similar functions in different
dynamic link libraries. Just grab all the imported procedures into an array of
procedures. Importing similar functions from different DLL's means you must use
procaddress excessively.
Knowing that you can have an array of procedures or functions is useful - but you may not immediatly see the need for them.
Here is how you access and fire off a procedure that is held in an array:
type
TMyProc = procedure(s: string);
var
MyProcArray: array of TMyProc;
begin
setlength(MyProcArray,2);
MyProcArray[0]('testing');
MyProcArray[1]('test');
end;
OR
type
TMyProc = procedure(s: string);
var
MyProcArray: array [0..1] of TMyProc;
begin
MyProcArray[0]('testing');
MyProcArray[1]('test');
end;
OR
if you are loading a bunch of functions from a library (DLL or SO)
type
TMyProc = procedure(s: string);stdcall;
var
MyProcArray: array of TMyProc;
MyLibHandle: THandle;
begin
MyLibHandle:= LoadLibrary('MyLib.dll'); //or MyLib.so
setlength(MyProcArray,2);
MyProcArray[0]('testing'); //launches procedure stored in array
MyProcArray[1]('test');
end;
Interesting syntax? Definitely.. but it works just as you thought it would.
This below may cause access violation in freepascal:
type
TMyProc = procedure(s: string);stdcall;
var
MyProcArray: array of TMyProc;
MyLibHandle: THandle;
begin
MyLibHandle:= LoadLibrary('MyLib.dll'); //or MyLib.so
setlength(MyProcArray,2);
MyProcArray[0]('testing'); //this causes run time error on program closing
MyProcArray[1]('test'); //this causes access violation
FreeLibrary(MyLibHandle);
end;
(Bug reported in July 2005, may be fixed soon)
Subject: Array of procedure, Array of function, array of procedures, array of functions, multiple procedures, multiple functions.
|