Interface implementation

Top  Previous  Next

What is translated > Types > Records, Classes, Interfaces > Interfaces > Non-generic interfaces > Interface implementation

In Delphi, interfaces are implemented by classes that inherit from one or more interface types and provide the required method implementations. At runtime, interface-based operations such as as_di<T>, Supports, and QueryInterface rely on the ability to resolve interface types dynamically. Delphi2Cpp reproduces this behavior in C++ by generating GetInterface logic and optional interface tables.

 

�� Manual Interface Resolution with DEFINE_INTERFACE_MAP

 

If the option for explicit interface tables is enabled in Delphi2Cpp, the translator generates macros such as DEFINE_INTERFACE_MAP, INTERFACE_ENTRY, etc., to produce inline GetInterface implementations directly within a class.

 

This mode is straightforward and transparent, but the generated map must be updated if the number of interfaces changes.

 

These macros compare the requested interface GUID (iid) with the known implemented interfaces and return the corresponding casted pointer:

 

 

bool GetInterface(const GUID& iid, void** obj) const override

{

    if (!obj) return false;

    *obj = nullptr;

    if (iid == __uuidof(IFoo))

    {

        *obj = static_cast<IFoo*>(const_cast<MyClass*>(this));

        return true;

    }

    return false;

}

 

This approach is straightforward and easy to debug, but it must be manually extended if the number of interfaces changes.

 

�� Compile-Time Interface Tables via InterfaceTableGenerator

 

If the option for automatic interface tables is enabled in Delphi2Cpp, the translator uses template metaprogramming (InterfaceTableGeneratorFromTuple) to construct the interface table at compile time from a std::tuple of implemented interface types.

 

This mode reduces boilerplate, avoids manual map maintenance, and supports RTTI-like behavior even in portable environments.

 

The generated table contains static mappings of interface GUIDs to function pointers capable of casting a raw void* to the corresponding interface pointer.

 

This is used in the generic base class TCppInterfacedObject<...>, which supports multiple interfaces and provides a QueryInterface implementation equivalent to Delphi's built-in behavior:

 

template <typename... Interfaces>

class TCppInterfacedObject : public TInterfacedObject, public Interfaces..., public ID2CObject

{

    ...

    virtual HRESULT __stdcall QueryInterface(const IID& iid, void** obj) override

    {

        for (int i = 0; i < InterfaceTableGen::Table.EntryCount; ++i)

        {

            if (*InterfaceTableGen::Table.Entries[i].IID == iid)

            {

                *obj = InterfaceTableGen::Table.Entries[i].Getter(this);

                AddRef();

                return S_OK;

            }

        }

        return E_NOINTERFACE;

    }

};

 

 

This approach is clean, extensible, and avoids code duplication. It supports automatic GetInterfaceTable() generation and enables RTTI-like behavior even in portable environments.

 

In Delphi, a class implements an interface simply by inheriting from it and implementing its methods. Delphi2Cpp maps this behavior directly to C++, either using compiler-specific base classes (for C++Builder) or portable infrastructure (for standard C++).

 

Below is a comparison of how a simple class TFooClass, implementing the interface IFoo, is translated.

 

 

Delphi

 

type

  TFooClass = class(TInterfacedObject, IFoo)

  public

    procedure DoSomething;

  end;

 

 

C++Builder

 

 

class TFooClass : public TCppInterfacedObject<IFoo>

{

public:

   void __fastcall DoSomething();

};

 

it Inherits from TCppInterfacedObject<IFoo>, which handles reference counting and QueryInterface.

 

 

Portable C++ (Explicit interface tables enabled)

 

 

class TFooClass : pubkic TCppInterfacedObject, public virtual IFoo

{

public:

    INTFOBJECT_IMPL_IUNKNOWN(System::TInterfacedObject)

    void DoSomething();

 

private:

  DEFINE_INTERFACE_ENTRIES(TFooClass)

  virtual System::PInterfaceTable GetInterfaceTable() const override { return &TFooClassInterfaceTable; }

};

 

DEFINE_INTERFACE_MAP(TFooClass)

  INTERFACE_ENTRY(TFooClass, IFoo)

END_INTERFACE_MAP(TFooClass)

 

 

- Inherits from TInterfacedObject and the interface directly.

- Uses macro-based interface table definitions and dispatch logic.

- DEFINE_INTERFACE_MAP(...) generates GetInterface() dynamically based on listed interfaces.

 

 

 

Portable C++ (Modern Style)

 

 

class TFooClass : public System::TCppInterfacedObject<IFoo>

{

public:

 

  void DoSomething();

};

 

- Uses TCppInterfacedObject<...> with template-based interface resolution.

- Interface table is generated at compile time using InterfaceTableGeneratorFromTuple.

- This style reduces boilerplate and scales well with multiple interfaces.

 

 



This page belongs to the Delphi2Cpp Documentation

Delphi2Cpp home  Content