Deprecated: Non-static method StringParser_Node::destroyNode() should not be called statically, assuming $this from incompatible context in /www/htdocs/w008ab83/ad/stringparser_bbcode/src/stringparser.class.php on line 356
AUDACIA Software - Über die Unverträglichkeit von Interfaces und dynamic_cast
AUDACIA Software

Über die Unverträglichkeit von Interfaces und dynamic_cast

Die Probleme der C++-Umsetzung von COM-Interfaces.
Moritz Beutel, 31.10.2008



  1. dynamic_cast<> mit C++-Klassen
  2. COM in C++
  3. dynamic_cast<> mit Delphi-Klassen
  4. Ein pragmatischer Workaround
  5. Referenzen
  6. Kommentare



COM-Interface-SpezifikationLayout-Anforderungen:Nicht mehr, nicht weniger.


dynamic_cast<> mit C++-Klassen


Was passiert also, wenn dynamic_cast<> auf ein Interface appliziert wird?
IMyInterface* intf = createObject ();
MyClass* mc = dynamic_cast <MyClass*> (intf);
void    __far * DEFCC   __DynamicCast(void      __far * objectPtr,
				      void      __far * vtablePtr,
				      void      __far * srctypPtr,
				      void      __far * dsttypPtr,
				      int               reference);
eine Compiler-Optionnegative Offsets der VMTHenry Spencer stellte vollkommen zutreffend fest: "If you lie to the compiler, it will get its revenge."


COM in C++

class IUnknown
{
public:
    virtual HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void **ppvObject) = 0;
    virtual ULONG STDMETHODCALLTYPE AddRef (void) = 0;
    virtual ULONG STDMETHODCALLTYPE Release (void) = 0;
};
typedef struct _IUnknownVtbl
{
    HRESULT (STDMETHODCALLTYPE * QueryInterface) (
        IUnknown* This,
        REFIID    riid,
        void**    ppvObject);

    ULONG (STDMETHODCALLTYPE * AddRef) (
        IUnknown* This);

    ULONG (STDMETHODCALLTYPE * Release) (
        IUnknown* This);
} IUnknownVtbl;

struct IUnknown
{
    const IUnknownVtbl* lpVtbl;
};

dynamic_cast<> mit Delphi-Klassen

darlegte, ist das VMT-Layout einer Delphi-Klasse anders als das einer C++-Klasse:

void	*__fastcall _EXPFUNC __DynamicCastVCLref(void *ptr, void *targetVMT);
void	*__fastcall _EXPFUNC __DynamicCastVCLptr(void *ptr, void *targetVMT);


Ein pragmatischer Workaround

class __declspec(uuid("{22807D4C-1770-472D-A44B-4D87B53D0189}")) MySelfAwareClass
    : public MyCppClass
{
    virtual HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void **ppvObject)
    {
        DO_QUERYINTERFACE (MySelfAwareClass)
        return MyCppClass::QueryInterface (riid, ppvObject);
    }
};

int _tmain (void)
{
    _di_IUnknown i = new MySelfAwareClass;

    MySelfAwareClass* msac;
    i->QueryInterface (__uuidof (MySelfAwareClass),
        reinterpret_cast <void**> (&msac));
}

Referenzen


[1] Der Quelltext der Runtime-Libraries von Delphi und C++Builder (in C++Builder enthalten)
[2] Raymond Chen, The layout of a COM object, 05.02.2004
[3] The C++ Standards Committee, State of C++ Evolution (Post-Antipolis 2008 Mailing), 30.06.2008


Kommentare



Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead in /www/htdocs/w008ab83/ad/phputils/dbc_mysql.php on line 112

Neuer Eintrag:

Name:
E-Mail:
Website:
Datum:
Anzahl der Zeichen in Ihrem Namen:
Text: