2010-12-29 12 views
16

Kann ich eine Klasse in eine DLL einfügen? Die Klasse i schrieb, ist dies:Wie verwendet man eine Klasse in DLL?

class SDLConsole 
{ 
     public: 
      SDLConsole(); 
      ~SDLConsole(){}; 
      void getInfo(int,int); 
      void initConsole(char*, char*, SDL_Surface*, int, int, int); 
      void sendMsg(char*,int, SDL_Surface*); 
      void cls(SDL_Surface*); 

     private: 
       TTF_Font *font; 
       SDL_Surface *consoleImg; 
       int width, pos, height, line, size, ctLine; 
       SDL_Surface* render(char*,int); 

}; 

Ich weiß, wie eine DLL zu laden und die Funktion innerhalb einer DLL verwenden, aber wie kann ich eine Klasse in einer DLL setzen? Vielen Dank.

+0

Ich glaube alles, was Sie brauchen, ist [hier] (http://msdn.microsoft.com/en-us/library/a90k134d.aspx) – icecrime

+0

Haben Sie es versucht? – BlackBear

Antwort

20

Wenn Sie dynamische Laufzeitverknüpfung verwenden (verwendet LoadLibrary zum Laden der DLL), können Sie nicht direkt auf die Klasse zugreifen. Sie müssen eine Schnittstelle für Ihre Klasse deklarieren und eine Funktion erstellen, die eine Instanz dieser Klasse zurückgibt:

class ISDLConsole 
{ 
    public:    
     virtual void getInfo(int,int) = 0; 
     virtual void initConsole(char*, char*, SDL_Surface*, int, int, int) = 0; 
     virtual void sendMsg(char*,int, SDL_Surface*) = 0; 
     virtual void cls(SDL_Surface*) = 0; 
}; 

class SDLConsole: public ISDLConsole 
{ 
    //rest of the code 
}; 

__declspec(dllexport) ISDLConsole *Create() 
{ 
    return new SDLConsole(); 
} 

Andernfalls, wenn Sie die dLL während der Ladezeit verknüpfen, verwenden Sie nur die Informationen von icecrime zur Verfügung gestellt: http://msdn.microsoft.com/en-us/library/a90k134d.aspx

+0

Dieser Weg ist viel robuster als '__declspec (dllexport)'. Selbst die Ladezeitverknüpfung sollte diese Methode verwenden. –

+0

@Ben: Warum ist es robuster? –

+5

Da nur das v-table-Layout zwischen Bibliothek und Client übereinstimmen muss, ist dies relativ einfach, sogar zwischen verschiedenen Sprachen.Auf der anderen Seite, mit '__declspec (dllexport)' muss alles übereinstimmen: Compiler-Hersteller, Compiler-Version, Kompilieroptionen, oder Sie werden entweder mit Namens-Mangling-Mismatch (Link-Fehler) oder einem One-Definition-Regelverletzung und entsprechende Abstürze. –

4

können Sie und alle Informationen, die Sie brauchen, sind auf this page und this page:

#ifdef _EXPORTING 
    #define CLASS_DECLSPEC __declspec(dllexport) 
#else 
    #define CLASS_DECLSPEC __declspec(dllimport) 
#endif 

class CLASS_DECLSPEC SDLConsole 
{ 
    /* ... */ 
}; 

Alles, was übrig bleibt, ist das Definieren des Präprozessorsymbols _EXPORTING beim Erstellen der DLL.

+2

Das ist nicht "alles was übrig ist". Sie müssen auch sicherstellen, dass derselbe genaue Compiler zum Erstellen der DLL und aller Clients verwendet wird, die ebenfalls mit den Compileroptionen übereinstimmen. Sie zahlen eine große Wartbarkeitsstrafe dafür, die Dinge so zu machen, die [reine virtuelle Schnittstelle wie von bcsanches vorgeschlagen] (http://stackoverflow.com/questions/4555961/how-to-use-a-class-in-dll/4556025) # 4556025) ist viel besser. –

+0

@Ben: Du hast wahrscheinlich recht, aber ich muss zugeben, dass ich die Dinge immer so gemacht habe und dass ich mir einfach nicht vorstellen kann, die 'pure virtual interface'-Methode für ein großes Projekt zu verwenden – icecrime

+0

Wenn du Module hast, die sind eng gekoppelt, weil sie alle lokal für ein einzelnes Projekt sind, warum nicht einfach statische Bibliotheken verwenden? –

12

Solution von bcsanches vorgeschlagen,

__declspec(dllexport) ISDLConsole *Create() 
{ 
    return new SDLConsole(); 
} 

Wenn Sie diesen Ansatz als suggested von bcsanches verwenden werden, dann stellen Sie sicher, dass Sie die folgende Funktion delete Ihr Objekt verwenden,

Definieren Sie solche Funktionen immer in Paar, wie es gewährleistet, dass Sie Ihre Objekte aus dem gleichen Heap/Speicherpool/etc, die sie erstellt wurden löschen. Siehe pair-functions

+0

Ich möchte eine DLL aus meiner C++ - Klasse erstellen und diese DLL in meiner C# -Anwendung verwenden. Kannst du mir das bitte auch zeigen? Was braucht es noch? wie kann ich meine dll in C# anrufen, wenn ich es auf diese weise erstelle? – Breeze

+1

@Hossein: Suche nach pinvoke in C#. Sie werden viele Themen dazu finden. – Nawaz

+0

Sie meinen, ich muss den herkömmlichen DIIIMport wie normale DLLs (wie user32.dll) verwenden? ok ich werde es versuchen – Breeze

2

Wenn Sie die Daten in einer Klasse verfügbar machen möchten, werden die oben genannten Lösungen es nicht schneiden. Sie müssen eine __declspec(dllexport) auf der Klasse selbst in der DLL-Kompilierung und eine __declspec(dllimport) in dem Modul, das auf die DLL verweist.

Eine übliche Technik ist, dies zu tun (Microsoft Assistenten produzieren Code wie folgt):

#ifdef EXPORT_API 
#define MY_API __declspec(dllexport) 
#else 
#define MY_API __declspec(dllimport) 
#endif 

class MY_API MyClass { 
    ... 
}; 

Dann sicher EXPORT_API macht, ist in dem DLL-Projekt definiert, und stellen Sie sicher, dass es nicht in dem Modul definiert ist, Links zur DLL.

Wenn Sie ein neues DLL-Projekt in Visual C++ von Grund auf erstellen und das Kontrollkästchen "Symbole exportieren" aktivieren, wird mit dieser Technik ein Beispielcode generiert.

Verwandte Themen