JLI Spieleprogrammierung Foren-Übersicht JLI Spieleprogrammierung

 
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen 
 medals.phpMedaillen   RegistrierenRegistrieren   ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

laufzeitfehler beim laden von dll
Gehe zu Seite 1, 2  Weiter
 
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Entwicklung
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
newby
JLI'ler



Anmeldedatum: 17.08.2007
Beiträge: 106

Medaillen: Keine

BeitragVerfasst am: 27.08.2008, 15:01    Titel: laufzeitfehler beim laden von dll Antworten mit Zitat

hallo, ich habe eine klasse geschrieben, die ein bischen dx verwaltet.

CPP:
#define EXPORT __declspec(dllexport)

#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")

#include <d3d9.h>
#include <d3dx9.h>
#include <map>

using namespace std;

struct SpriteInfo
{
   int width;
   int height;
};


class CDirectX
{
   private:

      LPDIRECT3D9                 lpD3D;
      LPDIRECT3DDEVICE9           lpD3DDevice;
      IDirect3DSurface9*         lpBackBuffer;
      LPD3DXSPRITE                lpSprite;

      map<char*, LPD3DXFONT> Fonts;
      map<char*, D3DCOLOR> FontColors;
      map<char*, LPDIRECT3DTEXTURE9> Sprites;
      map<char*, SpriteInfo> SpriteInfos;

      int ResolutionWidth;
      int ResolutionHeight;

   public:
      
      EXPORT CDirectX();
      EXPORT ~CDirectX();

      EXPORT void Init(HWND hWnd, int width, int height, bool windowmode);
      EXPORT void StartSzene();
      EXPORT void EndSzene();
      EXPORT void Shutdown();

      EXPORT void CreateFont(char* name, char* face, short width, short height, D3DCOLOR color, bool italic, short weight);
      EXPORT void PrintText(int x, int y, char* text, char* fontname);

      EXPORT void LoadSprite(char* name, char* filename);
      EXPORT void ShowSprite(char* name, int x, int y, short scale);




};


die funktionen werden später alle noch initialiesert, wäre aber zu lang.

Jetzt lade ich die dll dynamisch:

CPP:
#include <windows.h>

typedef void (*FUNCInit)(HWND, int, int, bool);
typedef void (*FUNCStartSzene)();
typedef void (*FUNCEndSzene)();
typedef void (*FUNCShutdown)();
typedef void (*FUNCCreateFont)(char*, char*, short, short, DWORD, bool, short);
typedef void (*FUNCPrintText)(int, int, char*, char*);
typedef void (*FUNCLoadSprite)(char*, char*);
typedef void (*FUNCShowSprite)(char*, int, int, short);


class CDirectX
{
   private:

      HINSTANCE hDirectXGraphics;

   public:

      CDirectX()
      {
         hDirectXGraphics = LoadLibrary("DirectXGraphics.dll");
         if(hDirectXGraphics != NULL)
         {
            Init = (FUNCInit)GetProcAddress(hDirectXGraphics, "Init");
            StartSzene = (FUNCStartSzene)GetProcAddress(hDirectXGraphics, "StartSzene");
            EndSzene = (FUNCEndSzene)GetProcAddress(hDirectXGraphics, "EndSzene");
            Shutdown = (FUNCShutdown)GetProcAddress(hDirectXGraphics, "Shutdown");
            CreateFont = (FUNCCreateFont)GetProcAddress(hDirectXGraphics, "CreateFont");
            PrintText = (FUNCPrintText)GetProcAddress(hDirectXGraphics, "PrintText");
            LoadSprite = (FUNCLoadSprite)GetProcAddress(hDirectXGraphics, "LoadSprite");
            ShowSprite = (FUNCShowSprite)GetProcAddress(hDirectXGraphics, "ShowSprite");
         }
      }

      ~CDirectX()
      {
         FreeLibrary(hDirectXGraphics);
      }


      FUNCInit Init;
      FUNCStartSzene StartSzene;
      FUNCEndSzene EndSzene;
      FUNCShutdown Shutdown;
      FUNCCreateFont CreateFont;
      FUNCPrintText PrintText;
      FUNCLoadSprite LoadSprite;
      FUNCShowSprite ShowSprite;
};


wenn ich jetzt versuche eine funktion im programm zu nutzen bekomme ich einen laufzeitfehler. Die reine instanzierung der klasse funktioniert, der handle auf die dll ist auch vorhanden.
Könnte es daran liegen, dass ich versuche auf memberfunktionen einer klasse zu verweisen, ohne die klasse instanziert zu haben?
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
xardias
JLI Master


Alter: 38
Anmeldedatum: 28.12.2003
Beiträge: 804
Wohnort: Palo Alto, CA
Medaillen: Keine

BeitragVerfasst am: 27.08.2008, 15:15    Titel: Antworten mit Zitat

Das dürfte so nicht funktionieren fürchte ich. Erzeugst du im Hauptprogramm eine Instanz von CDirectX hast du keinerlei Informationen über die Eigentliche größe der Klasse (mit allen Implementierungsbedingten Variablen etc).

Soweit ich weiß ist die übliche Vorgehensweise beim Auslagern von Klassen die Folgende:
- Erstelle ein Interface (sagen wir IDirectX) welches als rein virtuelle methoden Init, StartSzene, etc enthält.
- In deiner DLL Implementierst du das Interface.
- In der DLL exportierst du eine einzige Methode IDirectX* createDirectX() wo du die Klasse per new erzeugst und zurück gibst.
- In dem Hauptprozess kannst du dann createDirectX importieren, ausführen und hast eine funktionierende Implementierung der Klasse.

viel erfolg Smile
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Deviloper
Junior JLI'ler



Anmeldedatum: 31.05.2006
Beiträge: 77

Medaillen: Keine

BeitragVerfasst am: 28.08.2008, 13:29    Titel: Antworten mit Zitat

Hm jap, so kann man das machen. Das Problem ist hier auch, dass du einfach Memberfunktionen aufrufen willst, ohne dazu überhaupt ein Object zu haben. Du kannst nicht nur einzellne Memberfunktionen exportieren, das geht nur bei freien Funktionen oder mit kompletten Klassen Wink
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
newby
JLI'ler



Anmeldedatum: 17.08.2007
Beiträge: 106

Medaillen: Keine

BeitragVerfasst am: 28.08.2008, 19:07    Titel: Antworten mit Zitat

gibst dafür irgendwo ein beispiel, irgendwie bekomme ich das nicht auf die Reihe.

hab die dll jetzt so geändert:

CPP:
EXPORT CDirectX* GetClass_CDirectX()
{
   CDirectX* tmp = new CDirectX;
   return tmp;
}


und die hauptanwendung:

CPP:
/*hier hab ich die ganze Klasse deklariert genau wie in der dll, das problem ist, dass ich nicht die ganzen directx-header nochmal einbinden will, damit die typen stimmen*/

typedef CDirectX (*FUNCGetClass_CDirectX)();
HINSTANCE hDirectX = LoadLibrary("DirectXGraphics.dll");
FUNCGetClass_CDirectX GetClass_CDirectX = (FUNCGetClass_CDirectX)GetProcAddress(hDirectX, "GetClass_CDirectX");
CDirectX DirectX = GetClass_CDirectX();



jetzt bekomme ich lauter linkerfehler, mit nicht aufgelösten externen symbolen. Was mach ich denn da falsch?
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Deviloper
Junior JLI'ler



Anmeldedatum: 31.05.2006
Beiträge: 77

Medaillen: Keine

BeitragVerfasst am: 28.08.2008, 19:24    Titel: Antworten mit Zitat

Hmm anders Wink
CPP:
namespace interface
{
   struct DirectX
   {
      virtual ~DirectX();
      virtual void init(::HWND const&, const unsigned int, const unsigned int, const bool) = 0;
      virtual void start_scene() = 0;
      virtual void end_scene() = 0;
   };
};
dein Interface ... in der DLL dann
CPP:
struct DirectXImpl : public interface::DirectX
{
   ~DirectX();
   void init(::HWND const&, const unsigned int, const unsigned int, const bool);
   void start_scene();
   void end_scene();
};
die Implementierung des ganzen ... und eine Funktion:
CPP:
EXPORT interface::DirectX* create_directx()
{ return new DirectXImpl; }

EXPORT void destroy_directx(interface::DirectX* dx)
{ delete dx; }
... so ... dann in deinem Projekt einfach:
CPP:
int main()
{
    // funktion laden, fenster erzeugen und so ...
    interface::DirectX* ptr_directx(create_directx());
    ptr_directx->init(hWnd, 100, 100, true);

    // nachher löschen
    detroy_directx(ptr_directx);
}
fertig.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
newby
JLI'ler



Anmeldedatum: 17.08.2007
Beiträge: 106

Medaillen: Keine

BeitragVerfasst am: 28.08.2008, 20:27    Titel: Antworten mit Zitat

ich muss zugeben, dass ich das zum großen Teil nicht verstehe Sad
seh ich das richtig, dass ich mit return new "irgendwas" einfach eine neue instanz einer klasse oder struktur zurückgeben kann? ich versteh jetzt nicht ganz wie ich die instanz in der hauptanwendung benutzen kann. Erstmal hole ich mir per GetProcAdress die Funktion die mir die Instanz liefert. Ich kann aber nicht einfach eine Instanz einer Klasse speichern die ich nicht kenne. wie kann ich die klassendefinition übergeben? ich kann die ja nicht einfach in der dll und der main deklarieren, weil ich dann die directx-libs linken müsste in der main.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
xardias
JLI Master


Alter: 38
Anmeldedatum: 28.12.2003
Beiträge: 804
Wohnort: Palo Alto, CA
Medaillen: Keine

BeitragVerfasst am: 29.08.2008, 07:51    Titel: Antworten mit Zitat

Wenn ich das richtig sehe verstehst du das prinzip der Polymorphie noch nicht so ganz. Vielleicht wäre es da sinnvoller Prinzip erstmal ohne DLLs zu lernen.

Vielleicht hilft dir der Abschnitt Objektorientierte Programmierung in diesem Tutorial weiter:
http://tutorial.schornboeck.net/inhalt.htm
Vor allem der Teil über abstrakte Klassen.

Vielleicht probierst du auch erstmal das was du vor hast ohne DLLs zu implementieren jedoch mit einem Interface wie Deviloper es gezeigt hat. Dann kannst du (wenn alles funktioniert) dich daran machen die Implementierung des Interfaces in die DLL auszulagern, und musst an deinem Code eigentlich kaum was ändern.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
newby
JLI'ler



Anmeldedatum: 17.08.2007
Beiträge: 106

Medaillen: Keine

BeitragVerfasst am: 13.10.2008, 16:37    Titel: Antworten mit Zitat

ich habs nochmal versucht:

die dll:

CPP:
class virtual_DX
{
   public:
   virtual char* test() = 0;
};


class DX : public virtual_DX
{
   public:
   char* test() {return "test";}
};


extern "C"
{
   __declspec(dllexport) virtual_DX* GetDX()
   {
      return new DX;
   }
}



und die exe


CPP:
#include <iostream>
#include <windows.h>

using namespace std;


class virtual_DX
{
   public:
   virtual char* test() = 0;
};

typedef virtual_DX* (*FUNCGetDX)();
FUNCGetDX GetDX;


int main()
{
   HINSTANCE hDll = LoadLibrary("Polymorphie.dll");
   GetDX = (FUNCGetDX)GetProcAddress(hDll, "GetDX");
   
   virtual_DX* DirectX = GetDX();

   DirectX->test();

   system("pause");
   FreeLibrary(hDll);
   return 0;
}




Erstmal möchte ich wissen ob das was ich da gemacht habe Polymorphie ist. Danach interessiert mich noch, warum er nicht "test" ausgibt.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
DirectXer
Dark JLI'ler



Anmeldedatum: 05.02.2005
Beiträge: 1201
Wohnort: Köln
Medaillen: Keine

BeitragVerfasst am: 13.10.2008, 20:54    Titel: Antworten mit Zitat

newby hat Folgendes geschrieben:
Erstmal möchte ich wissen ob das was ich da gemacht habe Polymorphie ist.

Polymorphie ist (in OOP in Verbindung mit Kapselung und Vererbung), sobald zwei vom Typ gleiche objekte sich in ihrem Verhalten unterscheiden. Da du beides mal Objekte des Typs Virtual_DX* haben kannst, aber eines die Implementation der virtuellen Funktion test überschreibt, ist das hier Polymorphie.

newby hat Folgendes geschrieben:
Danach interessiert mich noch, warum er nicht "test" ausgibt.

weil du
CPP:
DirectX->test();
schreibst anstatt
CPP:
std::cout << DirectX->test();
oder
CPP:
MessageBoxA(0, "", DirectX->test(), MB_OK);
Razz Razz

Gruß DXer
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
newby
JLI'ler



Anmeldedatum: 17.08.2007
Beiträge: 106

Medaillen: Keine

BeitragVerfasst am: 14.10.2008, 14:17    Titel: Antworten mit Zitat

heißst das also das ich den compiler quasi verar***e, indem ich sage die Funktion GetDX() liefert ein Virtual_DX* zurück, obwohl sie eigentlich ein DX Objekt zurückgibt?

Zweiter Fehler war doof, geb ich zu Very Happy

Ich glaube zwar nicht, dass ich die Polymorphie verstanden habe, aber ich weiß jetzt wenigstens wie ich Klassen aus dlls exportieren kann Very Happy

Vielen Dank, ihr habt mir mal wieder sehr geholfen
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
DirectXer
Dark JLI'ler



Anmeldedatum: 05.02.2005
Beiträge: 1201
Wohnort: Köln
Medaillen: Keine

BeitragVerfasst am: 15.10.2008, 18:01    Titel: Antworten mit Zitat

Kein Problem ;)

newby hat Folgendes geschrieben:
heißst das also das ich den compiler quasi verar***e, indem ich sage die Funktion GetDX() liefert ein Virtual_DX* zurück, obwohl sie eigentlich ein DX Objekt zurückgibt?
Hmm nein verarschen tust du ihn nicht, da er genau weiß was passieren soll (rer ist ja der, der deinen Code in ausführbare Maschinensprache übersetzt). Das ist so korrektes Verhalten, nur die Leser deines Codes können anfangs vllt Probleme haben das nachzuvollziehen; wer das Prinzip aber kennt der weiß auch was passiert ;)

newby hat Folgendes geschrieben:
Ich glaube zwar nicht, dass ich die Polymorphie verstanden habe, aber ich weiß jetzt wenigstens wie ich Klassen aus dlls exportieren kann :D

Joa prinzipiell ist das gar kein großes Problem, es ist wahrscheinlich nur ungewohnt wenn man da den Verwendungszweck hinter nicht kennt. Kennst du Interfaces? Das sind (abstrakte) Klassen, die nur eine bestimmte Reihe von Methoden definieren, aber nicht implementieren. d.h. sie legen für eine Funktion den Namen, die Parameter und den Rückgabewert fest, aber kein bestimmtes Verhalten (also kein {...}). Wenn von dieser Klasse jetzt andere Klassen erben, dann müssen sie alle (rein virtuellen) Funktionen der Basisklasse übernehmen, d.h. sie übernehmen den Namen, die Parameter und den Rückgabewert, nur das Verhalten, also was die Funktion macht, implementieren sie selbst. Somit wird sichergestellt, dass alle ableiteten Klassen den gleichen Grundaufbau haben aber im Verhalten unterschiedlich sein können (ist beio sowas dann interpretationssache).

Gruß DXer
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
newby
JLI'ler



Anmeldedatum: 17.08.2007
Beiträge: 106

Medaillen: Keine

BeitragVerfasst am: 16.10.2008, 08:57    Titel: Antworten mit Zitat

jo, den verwendungszweck kenn ich schon, ich hab nämlich versucht eine klasse aus einer dll zu exportieren. Hat jetzt sogar funktioniert Wink Very Happy
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
newby
JLI'ler



Anmeldedatum: 17.08.2007
Beiträge: 106

Medaillen: Keine

BeitragVerfasst am: 17.10.2008, 17:03    Titel: Antworten mit Zitat

so, noch ne frage:

wie kann ich denn den konstruktor bzw. den dekonstruktor einer klasse erst spät binden? die klasse in der ich die funktionen als virtual kennzeichne heißst ja anders als die eigentliche klasse, ich soll also einen rückgabetypen angeben.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Fallen
JLI MVP
JLI MVP


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

BeitragVerfasst am: 17.10.2008, 20:49    Titel: Antworten mit Zitat

Ich verstehe nicht ganz was du für ein problem mit dem CTor hast? Wenn du mit interfaces arbeitest hast du doch vermutlich auch eine Funktion welche dir eine Instanz dazu erstellt, oder?

CPP:
IMyClass* CreateClass(ClassId, ParameterA, ParameterB)
{
  if (ClassId == DirectX)
    return new DirectXClass(ParameterA, ParameterB);
  else if (ClassId == OpenGl)
    return new OpenGlClass(ParameterA, ParameterB);

  return NULL;   
}


Du kannst also deinen CTor basteln wie du willst, im interface kannst du diesesn sowieso nicht deklarieren. Das geht aber mit dem DTor:
CPP:
struct IMyClass
{
  virtual ~IMyClass() {} // = 0; ist hier NICHT möglich
...
};

...

class DirectXClass : public IMyClass
{
  virtual DirectXClass();
};


Was genau meinst du eigentlich mit Rückgabetypen angeben?
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
David
Super JLI'ler


Alter: 39
Anmeldedatum: 13.10.2005
Beiträge: 315

Medaillen: Keine

BeitragVerfasst am: 18.10.2008, 13:43    Titel: Antworten mit Zitat

Zitat:

Du kannst also deinen CTor basteln wie du willst, im interface kannst du diesesn sowieso nicht deklarieren. Das geht aber mit dem DTor:
CPP:
struct IMyClass
{
  virtual ~IMyClass() {} // = 0; ist hier NICHT möglich
...
};



Warum?
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Entwicklung Alle Zeiten sind GMT
Gehe zu Seite 1, 2  Weiter
Seite 1 von 2

 
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