C anstatt C++ Code in vielen Bibliotheken! Warum?
-
Gut, dann poste hier, was genau das Problem sein soll.
Lizenzen nicht zu verstehen, heißt nicht, dass man sich aussuchen kann, was sie bedeuten könnten.
-
TrueTom schrieb:
Ein Anwender des Programms muss die Library verändern können, was bei Templates ohne den Quelltext des Programms schwierig ist...
Ist das Vorhandensein des Quellcodes nicht sowieso Voraussetzung? Somit gibt es das Problem nicht, welches auch immer du meinst.
-
TrueTom schrieb:
audacia schrieb:
RHBaum schrieb:
Nur C-schnittstellen sind compilerunabhaengig definiert. Symbole fuer Klassennamen erzeugt jeder compiler anders, so dass client(.exe) und server(.dll / .lib oder was auch immer ) nur bei gleicher compilerversion zusammen passen wuerden.
Das stimmt und ist sehr ärgerlich. Warum gibt es vom Standard denn keine Festlegung dafür?
Das lässt sich zemlich leicht umgehen, indem man in der Dll eine Funcktion GetAPI definiert, die einem einen Zeiger auf ene Klasse zurückliefert.
Wie stellst du dir das denn vor? Dein Programm weiß dann immer noch nicht, wo die Memberfunktionen sind, die es aufrufen muß...
-
audacia schrieb:
Wie stellst du dir das denn vor? Dein Programm weiß dann immer noch nicht, wo die Memberfunktionen sind, die es aufrufen muß...
Wie ich mir das vorstelle? Hmm, ich will jetzt nicht den Spruch von Dieter Nuhr bringen, auch wenn er so schön passen würde. War wohl mein Fehler, in ein deutsches Forum zu posten.
(Und damit der Post nicht ganz so sinnlos ist: Mach Dich mal schlau, wie virtual Funktionen in C++ implementiert werden. Danke.)
-
TrueTom: Wenn ich Dir nicht sage wie die Funktionen meiner Klasse
class Geheim { // Funktionsnamen nicht bekannt :) };
heißen, dann kannst Du sie auch nicht aufrufen. Übrigens auch nicht wenn ich sie virtual mache.
-
Jester schrieb:
TrueTom: Wenn ich Dir nicht sage wie die Funktionen meiner Klasse heißen, dann kannst Du sie auch nicht aufrufen. Übrigens auch nicht wenn ich sie virtual mache.
Das ist sicherlich richtig, ich versteh allerdings nicht, worauf Du hinaus willst?
-
Dann erklär doch bitte mal genauer wie das mit dem GetAPI funktionieren soll.
-
TrueTom schrieb:
Wie ich mir das vorstelle? Hmm, ich will jetzt nicht den Spruch von Dieter Nuhr bringen, auch wenn er so schön passen würde. War wohl mein Fehler, in ein deutsches Forum zu posten.
Einer von uns macht einen Denkfehler. Und er sollte sich nicht dazu herablassen, arrogante Sprüche von sich zu geben.
Und damit der Post nicht ganz so sinnlos ist: Mach Dich mal schlau, wie virtual Funktionen in C++ implementiert werden. Danke.
*Arroganz-mal-übergeh* Wieso virtual? Eine DLL soll eine Klasse exportieren anstatt der C-Funktionen, das hat doch mit virtual nichts zu tun!
Vielleicht reden wir allerdings auch aneinander vorbei. Dann sieh dir folgenden Code an:
Headerdatei für DLL:
class class_to_export_by_dll { private: int i; public: void set_i (int new_i); int get_i (void); };
Sourcedatei für DLL:
#include <iostream> void class_to_export_by_dll::set_i (int new_i) { std::cout << i << " |-> " << new_i << std::endl; i = new_i; } int class_to_export_by_dll::set_i (void) { return (i); }
Aufrufeprogramm-Sourcedatei:
#include <iostream> #include "dllheaderdatei.hpp" using namespace std; int main (void) { class_to_export_by_dll c1; c1.set_i (52); cout << c1.get_i () << endl; return (0); }
Und nun erkläre mir bitte, wie die DLL dem Programm sämtliche Member-Funktionsaddressen über eine GetAPI-Funktion bekannt machen soll (falls es das war, wovon du redest
)!
Moritz
-
// SuperSoftPlugin.hpp class SuperSoftPlugin { public: virtual void TestFunc1() = 0; virtual void TestFunc2() = 0; }
// MyPluginDll.cpp class MySuperSoftPlugin : public SuperSoftPlugin { // ... } SuperSoftPlugin *GetPlugin() { return new MySuperSoftPlugin; }
#include "SuperSoftPlugin.hpp" int main (void) { SuperSoftPlugin *MyPlugin = GetPlugin(); MyPlugIn->TestFunc1(); MyPlugIn->TestFunc2(); return 0; }
-
TrueTom: Was wenn jetzt mein Compiler und der, der die dll erstellt hat unterschiedliche Namen für die rein virtuellen Funktionen erstellen?
Stichwort: name-manglingDu hast das Problem nur mit ner Klasse ummantelt und viel syntaktischen Zucker drangeschmiert. Das Problem bleibt aber das selbe.
-
Jester schrieb:
TrueTom: Was wenn jetzt mein Compiler und der, der die dll erstellt hat unterschiedliche Namen für die rein virtuellen Funktionen erstellen?
Stichwort: name-manglingDein Compiler würde Namen für die virtual Functionen erzeugen? Cool...
Allerdings wozu? Um die Funktionen aufzurufen sicherlich nicht...
-
TrueTom schrieb:
Dein Compiler würde Namen für die virtual Functionen erzeugen? Cool...
Allerdings wozu? Um die Funktionen aufzurufen sicherlich nicht...
Natürlich erzeugt der Compiler dafür Namen! Wie soll er sie denn sonst aufrufen?
Zum Test habe ich folgendes als DLL übersetzt:
#include <windows.h> class __declspec (dllexport) c1 { public: virtual int get_val (void); }; class __declspec (dllexport) c2 : public c1 { public: virtual int get_val (void); }; int c1::get_val (void) { return (0); } int c2::get_val (void) { return (1); } #ifdef __BCPLUSPLUS__ int WINAPI DllEntryPoint (HINSTANCE, unsigned long, void*) #else int WINAPI DllMain (HINSTANCE, unsigned long, void*) #endif { return (1); }
Wenn ich die fertige DLL, übersetzt mit Borland C++, mit dem Dependency Walker öffne, sagt er folgendes über Funktionsexporte der DLL:
Ordinal Hint Function Entry Point 1 (0x0001) 1 (0x0001) @c2@get_val$qv 0x000012CC 0 (0x0000) 0 (0x0000) @c1@get_val$qv 0x000012C4
(:D)
Btw: Wenn ich den Code mit VC++ Toolkit 2003 übersetze, erhalte ich:
Ordinal Hint Function Entry Point 1 (0x0001) 1 (0x0001) ?get_val@c1@@UAEHXZ 0x00001050 0 (0x0000) 0 (0x0000) ?get_val@c2@@UAEHXZ 0x00001060
Die DLL hat also schon wieder ihr Ziel verfehlt - nämlich, compilerunabhängig zu sein. Was würde denn eine GetAPI-Funktion hier ändern können?
Moritz
-
Um das mal abzukürzen (TT ist wahrscheinlich Angler
)
Die Memberfunktionsnamen kommen allein aus dem Headerder "mangled name" ist nur für Funktionen der DLLEXPORT-Schnittstelle relevant. Deswegen deklariert man GetAPI als extern "C":
// shared header: class IFoo { public: virtual void CALLINGCONVENTION DoSomething() = 0; } extern "C" DLLEXPORT IFoo * GetAPI();
GetAPI kann compilerunabhängig aufgerufen werden. Wie auch immer der Compiler des DLL's die Namen verwursten würde: der Client-Compiler kennt IFoo und IFoo::DoSomething nur aus dem Header (das DLL muß ja gar nicht da sein). Zur Laufzeit wird DoSomething nicht mehr per Name gesucht, sondern über die VMT aufgerufen. Dabei werden nur noch die Parameter auf den Stack geschaufelt, der IFoo * dereferenziert ==> Zeiger auf VMT, Offset draufaddiert ==> Funktionszeiger auf IFoo::DoSomething. (Es erfolgt kein check mehr, ob die Signatur von DoSomething tatsächlich der deklarierten entspricht)
Praxisbeispiel: COM.
-
Danke, schöne Erklärung.
Trotzdem hilft es mir nichts, wenn ich eine stinknormale Klasse, die auch nicht-virtuelle Funktionen enthält, exportieren muß. So ganz bringt's das also auch nicht...
Moritz
-
Ja, in dem Fall müßtest du alles wrappen, was nur bedingt funktioniert.