Template exportieren - Mögliche Alternative
-
Hallo,
folgender Code sei vorhanden um ein "Wörterbuch" zu implementieren, soll jedoch jetzt nur als Beispiel dienen:
extern "C" { template<typename Tk, typename Tv> class __declspec(dllexport) xyz { private: Tk* keyArray; Tv* valueArray; public: xyz(); ~xyz(); void addPair(Tk key, Tv value){ keyArray = (Tk*)alloc(/*whatever*/); valueArray = (Tv*)alloc(/*whatever*/); // usw... } }; }Diesen Code würde ich gerne in einer statischen Bibliothek exportieren und in einem Programm, welches diese Lib nutzt, wie folgt verwenden:
// ... xyz<int, short> whatever; whatever.add(1,2); // ...Nun ist es ja leider nicht möglich, Templates zu exportieren.
Ich habe überlegt, einfach ein paar "Vorgaben" zu exportieren, wie z.B.extern "C" { class __declspec(dllexport) VorlageByteInt { private: xyz<BYTE, int> dasTemplate; public: //... }; class __declspec(dllexport) VorlageShortInt64 { private: xyz<short, long int> dasTemplate; public: //... }; // usw... }Allerdings scheint mir das nicht gerade die feine Art zu sein.
Wie löse ich das am besten?Gruß.
-
Wozu soll das gut sein? Templates liegen im Header. Den Header musst du sowieso deiner Bibliothek beilegen. Damit ist aber schon alles vorhanden, was der Benutzer braucht.
-
Schon, aber ich möchte ungerne das Template in der Headerdatei definieren.
Oder verstehe ich dich falsch?
-
Mit einiger Wahrscheinlichkeit ja. Templates sind Vorlagen, aus denen der Compiler zur Compilezeit Klassen bzw. Funktionen stanzt. Der Linker kann mit ihnen nicht mehr arbeiten -- nur noch mit den aus ihnen gestanzten Funktionen.
Da nur der Compiler mit Templates etwas anfangen kann, macht es wenig Sinn, sie aus einer DLL exportieren zu wollen, und damit der Compiler sie verwenden kann, muss er sie in Gänze kennen. Wenn die Template, um die es dir geht, zu deinem API gehören soll, wirst du daher nicht umhinkommen, sie in einem Header zu definieren und diesen auszuliefern -- sonst kennt der Compiler desjenigen, der deine Bibliothek benutzen will, die Template nicht und kann keine Klasse/Funktion daraus stanzen.
-
Ja genau, das ist mir schon klar, deshalb dachte ich es gäbe da evtl. eine "Alternative" um dieses Problem zu lösen... Vollständiges Template im Header wäre natürlich eine, aber das gefällt mir garnicht...

Gibt´s noch irgendwelche anderen Wege, um das Problem zu "umgehen"?
Ich muss nicht unbedingt einen finden, ich frage das aus reinem Interesse...
-
Zeig konkreten Code, dann kann man evtl. eine passende Loesung vorschlagen.
-
Die vollständige Definition eines Templates muss zur Compilezeit zur Verfügung stehen, da führt leider kein Weg vorbei.
Das__declspec(dllexport)kommt mir komisch vor, was bezweckst du damit? Da schon der Linker keine Templates instanzieren kann, geht es zur Laufzeit erst recht nicht.
-
BspCode steht oben

Dachte damit sage ich dem Compiler, dass ich die entsprechende Funktion oder in diesem Fall die entsprechende Klasse in die Lib exportieren möchte?
-
dllexport ist Windows-only und (wie der Name vermuten lässt) fürs exportieren aus DLLs gedacht. DLLs sind dynamische Bibliotheken, also das Gegenteil von statisch.
-
@Templ:
Bei einer statischen Bibliothek wird anstatt einer *.exe Datei eine lib-Datei erzeugt. Du programmierst ganz normal, indem du in die Header die Deklarationen und in die Source-Dateien die Definitionen schreibst
Wenn du die Bibliothek verwenden willst, musst du dem Compiler sagen, wo er die Deklarationen findest (also die Header Dateien). Diese includest du dann ganz normal.
Dem Linker musst du dann auch noch sagen, wo er die Lib-Datei findest, aus dieser wird dann zusammen mit *.obj-Dateien deiner Sourcefiles die *.exe deines Programmes.
Schreibe also ganz normal die Klasse in einen Header (weil die Templates verwendest musst du sie da ganz reinschreiben und nicht nur das, was man bei normalen Klassen benutzt). Mehr musst du in der Regel nicht tun.
Und was soll eigentlich das extern C? Das ist reines C++, da brauchst du kein extern C, oder irre ich mich?
-
Captain Obvious schrieb:
dllexport ist Windows-only und (wie der Name vermuten lässt) fürs exportieren aus DLLs gedacht. DLLs sind dynamische Bibliotheken, also das Gegenteil von statisch.

@Nathan: Ist mir alles bekannt, trotzdem danke

Extern "C" wird, soweit ich weiß, vorallem wegen überladenen Funktionen, die C nicht kennt, verwendet, um somit "kompatibel" zu sein...Aber zum Thema zurück, ich glaube es ist geklärt, dass es da keine "Alternative" gibt.
Danke euch

-
Eher umgekehrt...
Extern C ist für C++ Programme, die C Code verwenden, da die interne Signatur von C-Funktionen anders ist als die von C++ (wegen Überladung).
-
Okay, gut zu wissen

-
namespace party { int foo(bar*, float); }würde eben vom Compiler zu etwas wie
__party__foo_int_barp_float
als Name verwurstet werden (in der Realität nicht so primitiv), damit die Funktion für den Linker eindeutig ist.
extern "C" int foo(bar*, float);würde auch danach noch foo heißen.
-
Nathan schrieb:
Eher umgekehrt...
Extern C ist für C++ Programme, die C Code verwenden, da die interne Signatur von C-Funktionen anders ist als die von C++ (wegen Überladung).extern "C"kann auch in der Gegenrichtung verwendet werden, also wenn man in einer C++ Library eine Funktion definieren möchte, so dass sie aus einem C Programm aufgerufen werden kann.extern "C"bewirkt einfach nur dass die Bezeichner C-kompatibel dekoriert werden. Ob man die Bezeichner dann verwendet um etwas zu konsumieren oder zu exportieren ist egal.