Interface Programming Learning Notes under Delphi (original)

xiaoxiao2021-03-05  23

Interface Programming Delphi under Delphi Delphi

1.1 Why use the interface?

For example: There is such a ticket service, the cinema can sell tickets, the opera can sell tickets, the passenger station can also sell tickets, then we need to put the cinema, song

Both the theater and passenger stations are designed as a class architecture to provide ticket service? You must know that even managers can sell tickets, it is obvious that they are not suitable for the inheritance structure of the manager to the ticket service.

In the middle, we need only a common ticket service. So, the service of the ticket is an interface, the cinema, and the opera house, as long as they follow such a service definition, it can be very good.

Interaction and communication (if necessary).

1.2 How to use the interface in Delphi

1.2.1 Declaration Interface

Imyinterface =

Interface (IINTERFACE) / / Description (1)

['{63E072DF-B81E-4734-B3CB-3C23C7FDA8EA}'] // Description (2)

Function GetName

Const str: string: String;

STDCALL;

Function queryinterface

Const IID: Tguid;

Out obj): hResult;

stdcall; // Description (3)

Function _addref: integer;

STDCALL; // Make the interface reference number plus 1.

Function _Release: Integer;

STDCALL; // minus the number of interfaces to 1, when it is less than or equal to 0, the release action is released.

END;

Description (1): If there is a continuing relationship, fill the parent interface in parentheses, otherwise, such as: ImyInterface = Interface.

Description (2): This GUID is optional. If you want to implement an interface with COM features, you need to add it, Delphi is in the VMT table for the interface with the GUID.

The information of the interface generates an interface, such as the definition of the interface method, and the method parameter definition can be detailed.

Description (3): The interface must implement these three functions.

1.2.2 implementation of the interface

The interface service is implemented by a class.

TintfClass = Class (Tobject, ImyInterface)

Private

FCOUNTER: Integer;

FREFCOUNT: Integer;

public

Function QueryInterface (Const IID: Tguid; Out Obj): hResult; stdcall;

...

END;

1.2.3 Get the interface

a. Use type conversion.

VAR AINTF: IMYINTERFACE;

Begin

AOBJ: = TINTFCLASS.CREATE

Try

AINTF: = (iMyInterface (AOBJ);

...

b. Using the Delphi compiler to build a mechanism. Such as: AINTF: = AOBJ.

c. Use the QueryInterface method for the object. Such as Olecheck (Aobj.Queryinterface (IID, AINTF)); only COM interfaces with GUID can be accessed.

d. Using the AS operator.

The use of the AS operator must meet the following conditions: 1. The interface must be explicitly specified inherited from the IINTERFACE interface. 2. You must have a GUID value

The implementation class of the interface in Delphi7 must also inherit from TinterFaceDObject, such as

Tintfclass = Class (TinterFaceDObject, ImyInterface)

1.2.4 Interface and Object Life

Because Delphi will check the interface if it is not released after use, add the release code in the generated program, but it also brought the problem, as follows: Var

i: integer;

AOBJ: TINTFCLASS;

AINTF: IMYINTERFACE;

Begin

AOBJ: = TINTFCLASS.CREATE

Try

AINTF: = AOBJ;

AINTF.GETNAME ...

Finally

AINTF: = NIL;

Freeandnil (AOBJ);

END;

The above code execution will generate the illegal error, because the interface is released when the NIL is set, and freeandnil (AOBJ) will release the AINTF again, and set it to AINTF

This object has been released when NIL. Solving this problem As long as the lifetime of the interface is unable to interfere with the life of the object, just reduce the reference count in Release, not the release of the release.

Function Tintfclass._release: integer;

Begin

Result: = interlockedDecrement (freecount);

END;

1.2.5 Entrustment of Interface (Interface Delegation)

Divided into two: 1. Object interface commissioned 2. Class object commission.

The object interface is delegated, if there is already the following interface definition:

IIMPLINTERFACE =

Interface (IINTERFACE)

Function ConvertTousd (Const INTD: Integer): Double;

Function ConvertTORMB (Const INTD: Integer): Double;

END;

Then there is a class that implements the interface:

TIMPLCLASS = Class (Tobject, IIMPLINTERFACE)

Private

FREFCOUNT: Integer;

public

Function ConvertTousd (Const INTD: Integer): Double;

...

END;

IMPLEMentation

Function TIMPLCLASS.QUERYINTERFACE (Const IID: Tguid; Out Obj): HRESULT;

Begin

IF GetInterface (IID, OBJ) THEN

Result: = 0

Else

Result: = E_NOINTERFACE;

END;

Function TIMPLCLASS._RELEASE: Integer;

Begin

Result: = interlockedDecrement (freecount);

if Result = 0 THEN

DESTROY;

END;

...

Now there is another class TINTFSERVICECLASS to implement the IIMPLINTERFACE interface, do not redefine, you only need to use the TIMPLCLASS:

TintfServiceClass = Class (Tobject, IIMPLINTERFACE)

Private

FIMPLSERVICE: IIMPLINTERFACE;

// fsrvobj: TIMPLCLASS; // If it is used by the class object

public

CONSTRUCTOR CRETE; OVERLOAD;

DESTRUCTOR DESTROY; OVERRIDE;

Constructor Create (ACLASS: TCLASS); OVERLOAD;

Property MyService: IIMPLINTERFACE READ FIMPLSERVICE IMPLEMENTS IIMPLINTERFACE

//

Property MyService: TIMPLCLASS Read Fsrvobj IMPLEments IIMPLINTERFACE; // If it is entrusted with an object.

END;

The implementation is as follows:

Constructor TintFserviceClass.create;

Begin

FIMPLSERVICE: = TIMPLCLASS.CREATE

END;

Constructor TintfServiceClass.create (aclass: tclass);

VAR

TIMPLCLASS;

Begin

Instance: = TIMPLCLASS (ACLASS.NEWINSTANCE);

FIMPLSERVICE: = Instance.create;

END;

Destructor TintfserviceClass.DESTROY DESTRUCTOR

Begin

FIMPLSERVICE: = NIL; // Follow TIMPLCLASS to use reference counts to control object life cycles, see TIMPLCLASS DESTROY implementation.

inherited;

END;

1.2.6 interface and RTTI

Delphi defines the interface briefing in VMT-72 displacement: vmtintftable = -72.

related functions:

GetInterfaceCount; // Get the number of interfaces.

GetInterFaceTable; // Get the interface form.

Related structure:

TinterfaceEntry = Packed Record

IID: Tguid;

VTable: Pointer;

IOFFSET: Integer;

Implgetter: integer;

END;

PinterfaceTable = ^ TINTERFACETABLE;

TinterFaceTable = Packed Record

Entrycount: Integer;

Entries: array [0..9999] of tinterfaceentry;

END;

Self is a pointer to the VMT pointer, so: Self.GetInterFaceTable.EnTrycount is equivalent to:

Aptr: = ppointer (Integeer) ^) VMTINTFTABLE) ^;

Just add RTTI information to programs compiled in Delphi in the declaration, such as:

{$ M }

Iinvokable = Interface (Iinterface)

{$ M-}

The RTTI information of the interface is defined by the TINTFMetAdata record structure:

TintfMetadata = Record

Name: String; // Interface Name

UnitName: String; // Interface declaration program unit name

MDA: TINTFMETHENTRYARRAY; / / Save the dynamic array of method information in the interface

IID: tguid; // interface GUID value

INFO: PTYPEINFO; / / Describe the pointer to interface information

Ancinfo: ptypeinfo; // Describe the pointer to the parent information

Numanc: integer; // This interface inherits the number of methods from the parent interface

END;

The definition of TintfmethentryArray is as follows:

Type

TcallConv = (CCREG, CCCDECL, CCPASCAL, CCSTDCALL, CCSAFECALL);

TINTFMETHENTRY = Record

Name: String; // method name

CC: tcallconv; // Call convention

POS: integer; // Method in the interface paramect: integer; // method number

ResultInfo: ptypeinfo; // Description Method Information Pointer

SelfInfo: ptypeinfo; // Describe the information pointer of the method itself

Params: TINTFPARAMENTRYARRY; / / Description Dynamic array of parameter information

HASRTTI: Boolean; / / Do this method has a Boolean value of RTTI information

END;

TINTFMETHENTRYARRY = array of tintfmethentry;

Parameter information TINTFPARAMENTRY definition:

TINTFPARAMENTRY = Record

Flags: tparamflags;

Name: String;

INFO: PTYPEINFO;

END;

TTYPEINFO = Record

Kind: TTYPEKIND; // Data type

Name: SHORTSTRING; // Type information string format

END;

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

New Post(0)