Introduction to Delphi-based interface programming

Source: Internet
Author: User
Tags ticket

Why use an interface?

Here's an example: there's aTicket sales Service, the cinema can sell tickets, the Opera House can sell tickets, the bus terminal can also sell tickets, then whether we need to the cinema, Opera House and bus terminal aredesigned as a class architecture to provide ticket selling services? You know, even the manager can sell tickets, obviously not suitable for the manager to includeinheritance structure of ticket selling service, all we need is aCommon selling ticket service。 SoThe ticket service is an interface., cinemas, opera houses, whatever.Follow such a service definitionwill be able to interact and communicate with each other well (if needed).

   How to use Interfaces in Delphi

   1. Declaration Interface

IMyInterface = Interface (iinterface)//Instructions (1)
[' {63e072df-b81e-4734-b3cb-3c23c7fda8ea} ']//Instructions (2)
function GetName (const str:string): String; stdcall;

function QueryInterface (const IID:TGUID; out OBJ): HResult; stdcall; //Instructions (3)
function _addref:integer; stdcall; Adds 1 to the number of interface references.
function _release:integer; The stdcall;//causes the interface reference number to be reduced by 1, and the release action when it is less than or equal to 0.
End

   Instructions (1): If there is an inheritance relationship, the parent interface is filled in parentheses, otherwise it is omitted, such as: IMyInterface = interface this is OK.

   Instructions (2): thisGUIDOptional, if you want toImplementing a COM attributeinterface, you need to add, Delphi in the interface with the GUID at run time in the VMT table at the predetermined location to generate the interface information, such as the definition of interface methods, method parameter definition details.

   Instructions (3): An interface must implement these three functions.

   2, the implementation of the interface

   the interface service is implemented by the class.

Tintfclass = Class (TObject, IMyInterface)
Private
Fcounter:integer;
Frefcount:integer;
Public
function QueryInterface (const IID:TGUID; out OBJ): HResult; stdcall;
...
End

   3. Get the interface

A. Use type conversions. Such as:

var aintf:imyinterface;
Begin
Aobj: = tintfclass.create;
Try
aintf: = (IMyInterface (aobj);
...

B. Use the Delphi compiler built-in mechanism. such as: aintf: = Aobj.

C. Use the QueryInterface method of the object. such as Olecheck (Aobj.queryinterface (IID, aintf)); Only COM interfaces with GUIDs can be accessed.

D. Use the AS operator.

The following conditions must be met with the as operator:

1. The interface must be explicitly specified to be inherited from the IInterface interface.

2. Must have a GUID value

In the Delphi7implementation class of the interfacemust also beinherit from TinterfacedobjectDown, like:

Tintfclass = Class (Tinterfacedobject, IMyInterface)

   4. Interface and Object lifetime

Because Delphi will check the interface itself, if it is not released after use, add the release code in the generated program, but also because of this problem, such as the following code:

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 would generate an access violation error because the interface was disposed when nil was placed on the interface, and Freeandnil (aobj) would release aintf once, while the aintf
Nil when the object has been disposed. Solve this problem as long asdon't let the interface interfere with the life of the objectYes, inonly subtract reference count in releaseWithout doing the act of releasing.

function Tintfclass._release:integer;
Begin
Result: = InterlockedDecrement (Frefcount);
End

   5, the interface of the delegation (Interface delegation)

are divided into two types:

1. Object Interface Delegation

2. Class object Delegate.

. Object interface delegate, assuming that the following interface definition is available:

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 (Frefcount);
If Result = 0 Then
Destroy;
End
... ...

Now there is another class Tintfserviceclass to implement the Iimplinterface interface, without redefining it, just use the timplclass above to:

Tintfserviceclass = Class (TObject, Iimplinterface)
Private
Fimplservice:iimplinterface;
Fsrvobj:timplclass; If you're delegating with a class object,
Public
Constructor Create; overload;
destructor Destroy; Override
Constructor Create (Aclass:tclass); overload;
Property Myservice:iimplinterface read Fimplservice implements Iimplinterface;
Property Myservice:timplclass read Fsrvobj implements Iimplinterface; If you delegate with an object.
End

The implementation is as follows:

Constructor Tintfserviceclass.create;
Begin
Fimplservice: = timplclass.create;
End

Constructor Tintfserviceclass.create (Aclass:tclass);
Var
Instance:timplclass;
Begin
Instance: = Timplclass (aclass.newinstance);
Fimplservice: = instance. Create;
End

destructor Tintfserviceclass.destroy;
Begin
Fimplservice: = nil; Follow Timplclass use reference counting to control the object life cycle and see the destroy implementation of Timplclass.
inherited;
End

6. Interface and Rtti

In Delphi, the interface Gog pointer is defined at the VMT-72 Displacement: vmtintftable =-72.

Related functions:

Getinterfacecount; Gets the number of interfaces.
getinterfacetable; Gets the interface table.

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 (Pointer (self) ^) + vmtintftable) ^;

Simply use the m+/m-directive in the Declaration to add RTTI information to the program compiled in Delphi, such as:

{$M +}
Iinvokable = Interface (iinterface)
{$M-}

The RTTI information for an interface is defined by the TINTFMETADATA record structure:

Tintfmetadata = Record
name:string; Interface Name
unitname:string; The name of the program unit for the interface declaration
Mda:tintfmethentryarray; Dynamic array of method information in the storage interface
Iid:tguid; The GUID value of the interface
Info:ptypeinfo; A pointer describing the interface information
Ancinfo:ptypeinfo; A pointer that describes the parent information
Numanc:integer; The number of methods that this interface inherits from the parent interface
End

Tintfmethentryarray is defined as follows:

Type
Tcallconv = (Ccreg, cccdecl, ccpascal, Ccstdcall, Ccsafecall);
Tintfmethentry = Record
name:string; Method name
Cc:tcallconv; Invoke conventions
Pos:integer; Location of the method in the interface
Paramcount:integer; Number of parameters for the method
Resultinfo:ptypeinfo; Information pointer describing the method callback type
Selfinfo:ptypeinfo; Information pointers that describe the method itself
Params:tintfparamentryarray; Dynamic array describing the parameter information
Hasrtti:boolean; Whether this method has a Boolean value for Rtti information
End

Tintfmethentryarray = array of tintfmethentry;

Parameter information tintfparamentry definition:

Tintfparamentry = Record
Flags:tparamflags;
name:string;
Info:ptypeinfo;
End

Ttypeinfo = Record
Kind:ttypekind; Data type
name:shortstring; string format for type information
End

Introduction to Delphi-based interface programming

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.