DLL: Nur eine Methode (Create) exportieren, Restzugriff per Zeiger?
-
das extern "C" brauchst du nur, wenn du die namen nicht gemangelt haben willst.
das ist z.b. der fall wenn du die methdoe per "GetProcAddress" dynamisch
laden willst. deine create-methode heißt ungefähr "?CreateTest?vpZy@Test.c" oder
so in der richtung. da du aber C++ zeugs (class) nutzt, kannst du garkein extern
"C" verwenden.du linkst warscheinlich die test.lib dazu. dadurch findet er die methode dann.
die release methode kann er nicht finden, da sie in der exe nicht steht.
entweder du machst
1.)
__declspec(dllexport) davor
oder
2.)
du baust dir ein abstraktes interface:
struct IBase { virtual ~IBase(){} virtual void Release() = 0; }; IBase *CreateObject();das kommt in den header
die DLL leitet sich eine klasse davon ab:class Test : public IBase { public: // ... }; IBase *CreateObject() { return new Test; }schon kannst du die methode verwenden.
natürlich kannst du die create-methode statisch machen, aber dann kannst du sie
nicht dynamisch laden (musst du wissen ob du das willst)
-
Ok danke!
Mist, das ist jetzt blöd.Meine Klasse soll ja noch mehrere Methoden haben. Ich dachte mir halt, nur die Create()-Funktion zu exportieren, und alle anderen Methoden können in der Anwendung dann per Zeiger angesprochen werden.
Dies ist also garnicht möglich?
-
Und wie macht es dann eigentlich zB. d3d8.dll? Da wird nur Direct3DCreate8() exportiert und noch zwei, drei andere Funktionen, aber nicht das Klasseninterface..
Das mit dem Interface kapiere ich leider nicht.
-
Habe das gefunden: http://www.codeguru.com/cpp/w-p/dll/importexportissues/article.php/c123
Dabei wird den Methoden bei der ersten Möglichkeit einfach ein "virtual" vorangestellt, es ist dann nur eine globale "Create" Funktion nötig.
Was haltet ihr von dieser Möglichkeit?
Die zweite Möglichkeit ist irgendein Gefrickel mit unions, das spricht mich nicht an.
-
Hellolo schrieb:
Habe das gefunden: http://www.codeguru.com/cpp/w-p/dll/importexportissues/article.php/c123
Dabei wird den Methoden bei der ersten Möglichkeit einfach ein "virtual" vorangestellt, es ist dann nur eine globale "Create" Funktion nötig.
Was haltet ihr von dieser Möglichkeit?
Die zweite Möglichkeit ist irgendein Gefrickel mit unions, das spricht mich nicht an.
Die "virtual" Variante ist sehr üblich. COM funktioniert z.B. auch so, also auch Direct3D etc.
Ist IMO eine recht saubere Methode.Wenn du dann noch zusätzlich, wie es bei COM gemacht wird, die "Interface-Klassen" frei von sämtlichen nicht-public und nicht-virtual Dingen hältst (also keine Datenmember etc.), dann kann es auch kaum Probleme geben, wenn sich die Implementierung mal ändert, ohne dass man alle Clients neu compiliert. In den "öffentlichen" Header Files ändert sich ja nix, dadurch müssen Clients nicht neu compiliert werden.
Feine Sache.WENN man es braucht. Ansonsten lieber ganz normale __declspec(dllexport) Klassen.
-
hustbaer schrieb:
Wenn du dann noch zusätzlich, wie es bei COM gemacht wird, die "Interface-Klassen" frei von sämtlichen nicht-public und nicht-virtual Dingen hältst (also keine Datenmember etc.), dann kann es auch kaum Probleme geben, wenn sich die Implementierung mal ändert, ohne dass man alle Clients neu compiliert. In den "öffentlichen" Header Files ändert sich ja nix, dadurch müssen Clients nicht neu compiliert werden.
Oh, kannst du das nochmals genauer erklären?
Ich habe eine normale Klasse geplant, ohne Vererbungen, aber einfach alle Methoden virtual gemacht, die von außen ansprechbar sein, aber nicht als exportname auftauchen sollen (Geht in richtung Anticheat, da möchte ich jede Möglichkeit des Verschleierns nutzen).
Die Klasse sollte ich frei von nicht-public und nicht-virtual Dingen halten? Wieso das?
Ich dachte, solange sich die Funktionen nach außen nicht ändern, gibt es keine Probleme.
-
Guck Dir Punkt 1 - 3 von meinem Post an.
http://www.c-plusplus.net/forum/viewtopic-var-t-is-241095-and-highlight-is-dll+interface+simon.html
SimonEdit:
Die Klasse sollte ich frei von nicht-public und nicht-virtual Dingen halten? Wieso das?
Weil in C++ so ein Interface definiert wird.
-
Ok, aber ich will gar keine Interface-Klasse.
Ich mache einfach die Methoden meiner Klasse, welche ich von außen ansprechen möchte, virtual. Das gibt doch keine Probleme, oder?
zB.
class Test { public: Test(); virtual ~Test(); virtual void Release(); private: static long __stdcall DialogProcess(HWND windowHandle, unsigned message, WPARAM wParam, LPARAM lParam); void AnotherFunction(); }; extern "C" __declspec(dllexport) Test* CreateTest();Dabei kann ich dann halt ->Release() aus der Anwendung per Zeiger aufrufen, die anderen Funktionen sind halt intern genutzte...
Und, könntest du die "vielen anderen Möglichkeiten" erwähnen?
-
Hellolo schrieb:
Geht in richtung Anticheat, da möchte ich jede Möglichkeit des Verschleierns nutzen
Hellolo schrieb:
Ok, aber ich will gar keine Interface-Klasse.
Ah. OK. Dann hab' ich einfach falsch vermutet. Meist will man sowas aus anderen Gründen machen, und dann is gut, wenn man es mit reinen Interface-Klassen macht.
Hellolo schrieb:
Ich mache einfach die Methoden meiner Klasse, welche ich von außen ansprechen möchte, virtual. Das gibt doch keine Probleme, oder?
Nein, sehe keine Probleme.
Solange du immer alles compilierst wenn sich irgendwo was ändert, sollte alles klappen.
Aber wie gesagt: wenn sich irgendwo in der DLL was ändert, solltest du auch immer alle anderen DLLs und EXEn neu compilieren.
-
Aber warum eigentlich? Kommt es dann darauf an, ob man early oder late binding nutzt?
Ich denke mir halt, solange das public interface (die public Methoden) der Klasse in der DLL gleich bleibt, muss man auch nichts ändern, also genauso, als ob man die DLL jetzt weglassen würde.
Solange die Methoden einer Klasse nach außen gleich bleiben, muss man den Clientcode ja nicht umschreiben.Oder geht's da jetzt wirklich nur darum, wenn man early binding nutzt, also eine .lib mitlinkt? Bei late binding ist es doch egal, da die Funktionen erst zur Laufzeit bekannt werden... eine veränderte DLL ändert dann doch nix am Kompilat.
