JLI Spieleprogrammierung Foren-Übersicht JLI Spieleprogrammierung

 
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen 
 medals.php?sid=5e2b6ed6967a2a7ee3167a8e72940f1eMedaillen   RegistrierenRegistrieren   ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

Interfaces/Guids für alle

 
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Tutorials
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
Fallen
JLI MVP
JLI MVP


Alter: 40
Anmeldedatum: 08.03.2003
Beiträge: 2860
Wohnort: Münster
Medaillen: 1 (mehr...)

BeitragVerfasst am: 18.03.2009, 22:51    Titel: Interfaces/Guids für alle Antworten mit Zitat

Einleitung:

Hier der Vorgänger auf dem dieser Artikel aufbaut:
http://www.jliforum.de/board/viewtopic.php?t=4800

Das Problem mit dem vorherigen Artikel war, dass dieser nur auf Microsofts VisualStudio/C++ ausgelegt war und daher nicht unter zB gcc kompiliert werden konnte und somit alles andere als portabel war.

Dieser Artikel soll dieses problem beseitigen indem zuerst Guids für alle zuer verfügung gestellt werden und gezeigt wird wie man Interfaces mit diesen verwenden kann.

Guids:

Guids sind eine 128Bit Datenstruktur welche es ermöglichen soll bestimmte Daten eindeutig zu kennzeichnen. korrekt erstellte Guids sind Weltweit eindeutig. Mehr Informationen dazu sind im passenden Wiki Artikel zu finden.

Ich stelle dies durch eine einfache Struktur dar:

CPP:
struct r_Guid
{
   unsigned long  Data1;
   unsigned short Data2;
   unsigned short Data3;
   unsigned char  Data4[ 8 ];

   bool operator==(const r_Guid& lr_Other) const
   {
       return (
        ((unsigned long *) this)[0] == ((unsigned long *) &lr_Other)[0] &&
        ((unsigned long *) this)[1] == ((unsigned long *) &lr_Other)[1] &&
        ((unsigned long *) this)[2] == ((unsigned long *) &lr_Other)[2] &&
        ((unsigned long *) this)[3] == ((unsigned long *) &lr_Other)[3]);
   }

   bool operator!=(const r_Guid& lr_Other) const
   {
      return !(*this == lr_Other);
   }
};


Dies entspricht in etwa der Struktur welche von Microsoft verwendet wird nur die 2 Operatoren wurden hinzugefügt.

Da wir auf das __declspec Keyword verzichten müssen (MS only) sind wir in der Not einen Ersatz zu finden um unsere Interfaces mit den Guids auszustatten, unter MS ist dies sehr einfach:

CPP:
struct __declspec(novtable) __declspec(uuid("{EDFDE891-F04D-4061-8CCC-F95959C16354}")) iBaseObject


Keine zusätze die wir erst includen müssen, oder aktivieren müssen. Nun wir müssen etwas mehr tun.

Als erstes erstellen wir uns 2 kleine Helfer, etwas das es uns ermöglicht das wir GUIDS an ein Interface binden können:

CPP:
template <typename T> struct UUID_Traits;

#define DEFINE_IID_TRAITS(a, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
template<> struct UUID_Traits<a>\
{\
   static r_Guid GetIID()\
   {\
      const r_Guid lr_Guid = { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } };\
      return lr_Guid;\
   }\
};


Wichtig für die spätere Verwendung ist dabei das Macro:

CPP:
#define DEFINE_IID_TRAITS(a, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)


Schwer zu durchblicken aber hier die Erklärung:

Alles was das Macro benötigt ist der Name unseres Interfaces (Parameter 'a') und eine GUID (Parameter 'w1, w2, b1, b2, b3, b4, b5, b6, b7, b8'), die GUID kann man hier wieder aus einem GUID Generator bekommen. Leider sind die meisten GUIDS in dieser Form:

Zitat:
{B48C1F60-8C63-40fa-8B84-F274F3906664}


Wir benötigen aber diese Form:

Zitat:
0xb48c1f60, 0x8c63, 0x40fa, 0x8b, 0x84, 0xf2, 0x74, 0xf3, 0x90, 0x66, 0x64


Um das zu umgehen kann man sich entweder für r_Guid einen Kontruktor schreiben welcher einen String annimmt und diesen parst, oder man teilt die obere variante so auf das man die untere erhält. Wir nehmen vorerst die 2te Variante.

Interfaces:

Wir können nun bereits unser Interface mit einer GUID ausstatten:

CPP:
struct iTestInterface
   : virtual iBaseObject // das gab es im vorherigen Artikel
{
   virtual void TestMethod() = 0;
};

DEFINE_IID_TRAITS(iTestInterface,
   0xb48c1f60, 0x8c63, 0x40fa, 0x8b, 0x84, 0xf2, 0x74, 0xf3, 0x90, 0x66, 0x64);


Abstossend nicht wahr?

Eine Erleichterung könnte dies hier geben:
CPP:
#define interface(a, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
   struct a; \
   DEFINE_IID_TRAITS(a, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
   struct a : virtual iBaseObject


Dies macht im Grunde nichts anderes als das was wir getan haben nur etwas hübscher und es ist nicht mehr nötig unsere GUIDS nach dem Interface festzulegen durch die forward decleration unseres Interfaces:

CPP:
interface(iTestInterface, 0xb48c1f60, 0x8c63, 0x40fa, 0x8b, 0x84, 0xf2, 0x74, 0xf3, 0x90, 0x66, 0x64)
{
   virtual void TestMethod() = 0;
};


Es sieht sogar etwas hübscher aus als die alte MS only Variante.

__uuidof(...) können wir nun auch nicht mehr verwenden doch dafür gibt es Abhilfe:

CPP:
template <typename T> inline r_Guid uuidof(T&)
{
   return UUID_Traits<T>::GetIID();
}

template <typename T> inline r_Guid uuidof()
{
   return UUID_Traits<T>::GetIID();
}

template <typename T> inline r_Guid uuidof(T*)
{
   return UUID_Traits<T>::GetIID();
}


Benutzt wird es zB in dieser Form:

CPP:
r_Guid lr_Guid = uuidof<iTestInterface>();


Der Nachteil ist das wir uuidof nur auf Interfaces anwenden können nicht auf die Implementierungen, da diese keine GUID zugewiesen bekommen haben, gebraucht wird dies allerdings sowieso nicht wenn man sich konsequent daran hält mit Interfaces zu arbeiten anstatt mit den tatsächlichen Implementierungen.
_________________
"I have a Core2Quad at 3.2GHz, 4GB of RAM at 1066 and an Nvidia 8800 GTS 512 on Vista64 and this game runs like ass whereas everything else I own runs like melted butter over a smokin' hot 18 year old catholic schoolgirl's arse."
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Tutorials Alle Zeiten sind GMT
Seite 1 von 1

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.


Powered by phpBB © 2001, 2005 phpBB Group
Deutsche Übersetzung von phpBB.de

Impressum