Calling a Private Method of Other Class
Sometimes it is necessary to call a private method of a class saved in another module. It contradicts the OOP principles used in Delphi, but one can try to execute such an operation. Let us consider as an example a case when it is necessary to load/save all the properties of TPersistent descendants, e.g. of an object of TFont class.
There exist standard Delphi classes TReader, TWriter designed to load/save properties of an object. The methods TWriter.WriteProperties(Instance: TPersistent) and TReader.ReadProperty(AInstance: TPersistent) are the most suitable for our purposes. The WriteProperties method allows for writing all properties of the TPersistent descendants into the stream. A call of the ReadProperty method within a loop allows the user to read all the previously saved properties from the stream.
Let us consider a procedure of saving the properties.
With Delphi5, it is evident: the declaration of the WriteProperties method is located in the protected section of the TWriter class, and it is easy to call it:
However, with Delphi4 the situation is more complicated: the WriteProperties method is located in the private section of the TWriter class, and a standard use of Delphi allows the user to call this method only from the module with the TWriter class, i.e. from classes.pas module. This problem seems to be insoluble because it is impossible to add a user code to classes.pas module or call the WriteProperties method from another module. But further in this article we are going to prove that this problem has a solution.
Please note that WriteProperties is a static method, i.e., its address is set during the compilation of the program. WriteProperties is called within the public method TWriter.WriteCollection.
To call WriteProperties, it is necessary to know its address. Let us try to determine it using the public method WriteCollection. One needs to develop a simplest project with a call of the WriteCollection method. This project must have a break point at the call of WriteCollection. Let us run this project: it will go up to the break point. Then we open the CPU window and enter the WriteCollection method by pressing the F7 key (Trace Info). Now we have reached the most interesting point of our technique: we need to find the WriteProperties call within the WriteCollection method and to calculate the offset (in bytes) of the "call TWriter.WriteProperties" command with respect to the starting point of the WriteCollection method. In the given case this offset is equal to $36 + 1 bytes. Thus, the code designed to determine the WriteProperties method address is the following:
After a series of experiments we have encountered a problem. The code shown above became inoperative when the project was compiled with standard packages, which is logical, because the packages are absolutely identical to dll files, and the entry points in all the procedures of a package are grouped in the table. But there ain't such thing as an insoluble problem. Here is the new code:
let us add few commands to increase the robust of this code:
Now that we have determined the WriteProperties address, we only need to call it:
The TReader.ReadProperty address can be determined similarly.
Where can it be used?
What are the advances of this technique?
What are the disadvantages of this technique?
You can download the demonstration project and study the source code described above. You can use this code in your own applications, but I reject any responsibility for possible consequences of its use. On the other hand, we proved that 'non-standard' programming techniques can lead to interesting results like calling a private method of another class declared in another program module.
The problems described above arose during the development of the shareware project Storage Library, which uses this technique to load/save all the properties of the TPersistent object descendants, e.g. TEdit.Font, TForm.Icon or TImage.Picture. More information on the Storage Library project can be found on Web server of Deepsoftware.RU company at http://www.deepsoftware.ru/rsllib/
[ Components ] [ Programs ] [ Articles ] [ Links ] [ Contacts ]
Copyright © 2000-2007 DeepSoftware.Com. All Rights reserved.