Delphi.net internal implementation analysis (2)

zhaozj2021-02-16  69

Delphi.net internal implementation analysis (2)

There are three methods left in the Unit class $ Wakeup () by Delphi.net; Finalization () completes the functionality similar to the Finalization section in the Delphi unit; the last helloworld () function is also automatically generated, using the Unit class name space name naming , As the HelloWorld here, complete the functionality of the Initialization section similar to the Delphi unit, such as in the .dpr, complete the program functionality between Begin End. From the CLR point of view, after loading the accessories compiled by Delphi.Net, the static constructor (i.e., the HelloWorld.Unit..cctor () function in this example is positioned by Metadata (ie, the HelloWorld.Unit..cctor () function in this example), call The MAIN function of the class (ie the HelloWorld.Unit.HelloWorld () method in this example). In the static constructor of the program entry class. In the work of the Mount Unit destructor (this case, the HelloWorld.Unit.Finalization () function is to work on the system level end call list. The following pseudo-code HelloWorld.Unit..cctor unit HelloWorldtype Unit = class procedure .cctor (); proceudre HelloWorld (); ... implementationprocedure Unit..cctor (); begin Borland.Delphi.System.Unit._AddFinalization (new Borland.delphi.system._finalizehandler (null, helloworld.unit.Finalization); helloWorld.Unit.HelloWorld (); end; helloworld.Unit.Finalization method is the Finalization Festival code for the HelloWorld.Unit class, used to uninstall in unit Timely - chamification; borland.delphi.system._finalizehandler is an event delegation type defined in the Borland.Delphi.system unit (borland.delphi.system.Unit._addFinalization is a full-class function of Borland.Delphi.system unit _Addfinalization.

In the Borland.Delphi.system unit, you can see the current code // -------------------------------- ------- Borland.Delphi.System.pas - type _FinalizeHandler = procedure of object; var OnProcessExit: _FinalizeHandler; procedure _AddFinalization (f: _FinalizeHandler); begin OnProcessExit: = _FinalizeHandler (System.Delegate.Combine (System. Delegate (@f), System.Delegate (@OnProcessExit))); end; {$ IF SimpleFinalizer} type TFinalObject = class public procedure Finalize; override; end; procedure TFinalObject.Finalize; begin OnProcessExit; inherited; end; {$ ELSE } procedure ProcessExitHook (sender: System.Object; eventArgs: System.EventArgs); begin OnProcessExit; end; {$ IFEND} {$ IF SimpleFinalizer} var _GlobalFinalObject: TObject; {$ IFEND} initialization {$ IF SimpleFinalizer} {$ MESSAGE WARN 'Using simple finalizer'} _GlobalFinalObject: = TFinalObject.Create; {$ ELSE} System.AppDomain.CurrentDomain.add_ProcessExit (ProcessExitHook); // System.AppDomain.CurrentDomain.add_ProcessExit (// System.EventHandle R.Create (nil, intptr (@ProcessExiThook)); {$ ifend} // -------------------------------------------------------------------------------------------------------------------------------------- ----------- borland.delphi.system.pas - First event entrustment type _finalizeHandler definition, and the same class member function pointer syntax in Delphi. In Delphi, such pointers are implemented in a TMETHOD structure, saving the object instance and the pointer to the member function, respectively, with the function pointer in the normal C / C language. //-----------------------------------------System.pas - TMETHOD = Record Code, Data: Pointer; End; // --------------------------------------- --System.pas - The implementation of the event in the CLR is very similar to Delphi (after all, it is the same person's design :), but only wrapped it with a class, specifically explain the "MS .NET Framework program" of the cattle Jeffrey Richter Design "book. Therefore, the definition of the event handler function in delphi.net can not move.

Unlike Delphi, Deltegate in the CLR can be subscribed by multiple processing functions at the same time, and directly represents OnProcessExit = new _finalizehandler (...) in the language of C # a class directly support event. In the _addfinalization function call, I hope that Borland can add a representation syntax in the C # language in the future, so that it is clear, if there is an operator overload, it is cool, and the bottom layer It is implemented with CLR. The Delphi.NET then provides two ways to implement the unit first-level Finalization function, and use a simpler method to manage life cycles directly by the _GlobalNAlObject object. Because _GlobalFinalObject object is a global object, its life is constructed throughout the program, and the entire program is over when it is released. The TFinalObject is overloaded with a Finalize method. If the method is overloaded, the GC garbage reclaims this method before the object is released. This ensures that all units of the Finalization section of all units are successively called until the Borland.Delphi.system unit is uninstalled. If you do not define SimpleFinalizer, use more complicated methods. The ProcessExiok function is attached to the process end event of the current AppDomain application domain, and calls before the process ends. After the hooking parallelism is handled, .cctor will call HelloWorld () points to the unit initialization code or program execution code. To call the helloworld.Unit.HelloWorld () function public static void helloworld () {borland.delphi.system.unit. $ Wakeup (); borland.delphi.system.Unit._writeln (borland.delphi.system. Unit._write0wstring (borland.delphi.system.Unit.output, "Hello delphi!")); Borland.delphi.system.unit .__ Iotest ();} $ Wakeup () and __iotest () are responsible for waking up and IO test, there is no role. The middle code is Writeln ('Hello Delphi!'); The implementation of this line code, and then reviews when we specifically parse the borland.delphi.system unit. 1.3 Class implementation After analyzing a simplest delphi.net program, let's take a look at the complex examples. This example defines a TDEMO class, completes the same function as the previous example, but is completed in the class.

//----------------------------------------Helloworld2.dpr-program HelloWorld {$ Appype console} type tdemo = class public procedure hello; end; {tmemo} procedure tdemo.hello; begin writeln ('Hello Delphi!'); End; begin tdemo.create.hello; end .//--- -------------------------------------- HelloWorld2.DPR - Open HelloWorld2.exe with ILDASM, You can find a TDEMO class in the HelloWorld name space, and the code in the HelloWorld.Unit.HelloWorld () function is also changed to public static void helloworld () {borland.delphi.system.unit. $ Wakeup (); new helloworld. TDEMO (). Hello ();} Let's take a look at the implementation of TDEMO. We will find that TDEMO is inherited directly from the System.Object class. In a traditional Delphi language, if you do not explicitly specify its parent class when you define a class, you can specify its parent class as the TOBJECT class; in delphi.net, because the system architecture is integrated into the CLR standard In the library's architecture, it is impossible to define a set of inherited trees for Delphi.net, so all TOBJECT changes to System.Object. Introducing the important concept of Class Helper in Delphi.NET to maximize the TOBJECT in the original code. The concept of Class Helper can be said to be a very clever compromise that allows the user to add new features to the exterior of the existing tree, but limit the data member cannot be added. Because Borland wants to transplant its VCL architecture to the CLR's BCL, although the BCL and VCL structures are very similar (originally designed), there are some details from the name to function, and Borland has no BCL source. Code, M $ is not likely to allow other vendors to modify their source code. This causes the paradox of Borland to modify its architecture without modifying the BCL architecture, huh, huh. The result of the compromise is the appearance of the Patch syntax of Class Helper. The reason why the patch syntax is because Class Helper is allowed to add new features to it on the basis of not modifying the existing class. Class Helper is defined to increase data members so that the program changes due to changing the originally classical physical structure. This effect is image that hits a patch to the original class, so that the original BCL class is very similar to the corresponding class of the VCL, no matter what it looks. For example, in delphi.net, the TOBJECT type is actually an alias of System.Object. The TOBJECTHELPER is a TOBJECT patch, providing TOBJECT functions that is compatible with TOBJECT in VCL, which is implemented through System.Object, just the name and usage.

//----------------------------------------- ,land.delphi.system.pas --type TObject = System.Object; TObjectHelper = class helper for TObject procedure Free; function ClassType: TClass; class function ClassName: string; class function ClassNameIs (const Name: string): Boolean; class function ClassParent: TClass; class function ClassInfo : TObject; class function InheritsFrom (AClass: TClass): Boolean; class function MethodAddress (const Name: string): TObject; class function SystemType: System.Type; function FieldAddress (const Name: string): TObject; procedure Dispatch (var Message ); End; // ----------------------------------------- borland.delphi .Stem.pas - this, Borland is concise but not perfectly solves this paradox. However, it is foreseeable that the emergence of this grammar will trigger a fierce debate in the future, because in any case, this grammar is in fact impacting the purity of OO design ideas. Later we analyze the use of Class Helper when we analyze the borland.delphi.system unit. In the TDEMO class, another is worth noting is a nested subclass named @metadDemo. In Delphi, each class has a corresponding Metclass Metaclass, which can be accessed by Class of TmyClass definition TMYCLASS, or can be accessed directly from the class method. The category is implemented in the VMT table in such objects. In Delphi.NET, the memory layout of the class is no longer fully controlled by Delphi, and the VMT may be bind to each object. So Borland represents such a category of this class through a nested subclass of the "@ Meta Class Name" as class name. For example, TDEMO is a TDEMO. @ MetaCemo class, inherited from borland.delphi.system._tclass class.

转载请注明原文地址:https://www.9cbs.com/read-22625.html

New Post(0)