Ich habe zwei dll-exportierte Klassen A und B. Die Deklaration von A enthält eine Funktion, die einen std::vector in ihrer Signatur wie verwendet:
class EXPORT A{
// ...
std::vector<B> myFunction(std::vector<B> const &input);
};
(EXPORT ist das übliche Makro zum Einfügen _ declspec(dllexport)/ _declspec(dllimport) entsprechend.)
Wenn ich über die Probleme lese, die mit der Verwendung von STL-Klassen in einer DLL-Schnittstelle verbunden sind, kann ich zusammenfassend feststellen:
-
Die Verwendung von std::vector in einer DLL-Schnittstelle würde erfordern, dass alle Clients dieser DLL mit der gleichen Version des gleichen Compilers, da STL-Container nicht binärkompatibel sind. Schlimmer noch, je nach Verwendung dieser DLL durch Clients zusammen mit anderen DLLs kann die "instabile" DLL-API diese Client-Anwendungen zerstören, wenn Systemaktualisierungen (z. B. Microsoft KB-Pakete) installiert werden (wirklich?).
-
Trotzdem kann std::vector bei Bedarf in einer DLL-API verwendet werden, und zwar durch den Export von
std::vector<B>
mögen:template class EXPORT std::allocator<B>; template class EXPORT std::vector<B>;
Allerdings wird dies normalerweise in dem Zusammenhang erwähnt, wenn man std::vector als Mitglied von A (http://support.microsoft.com/kb/168958).
-
Der folgende Microsoft Support-Artikel beschreibt, wie man auf std::vector-Objekte, die in einer DLL erstellt wurden, über einen Zeiger oder Verweis aus der ausführbaren Datei heraus zugreifen kann (http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q172396). Die obige Lösung zur Verwendung von
template class EXPORT ...
scheint ebenfalls anwendbar zu sein. Der unter dem ersten Aufzählungspunkt zusammengefasste Nachteil scheint jedoch bestehen zu bleiben. -
Um das Problem vollständig zu beseitigen, müsste man std::vector einpacken und die Signatur von
myFunction
, PIMPL usw..
Meine Fragen sind:
-
Ist die obige Zusammenfassung richtig, oder übersehe ich hier etwas Wesentliches?
-
Warum erzeugt die Kompilierung meiner Klasse 'A' nicht die Warnung C4251 (class 'std::vector<_Ty>' needs to have dll-interface to be used by clients of...)? Ich habe keine Compiler-Warnungen ausgeschaltet und erhalte keine Warnung bei der Verwendung von std::vector in
myFunction
in der exportierten Klasse A (mit VS2005). -
Was muss für den korrekten Export getan werden?
myFunction
in A? Ist es praktikabel, einfach zu exportierenstd::vector<B>
und dem Zuweiser von B? -
Was sind die Auswirkungen der Rückgabe von std::vector by-value? Angenommen, eine ausführbare Client-Datei wurde mit einem anderen Compiler (-version) kompiliert. Bleibt das Problem bestehen, wenn der Vektor bei der Rückgabe von by-value kopiert wird? Ich denke ja. Ähnliches gilt für die Übergabe von std::vector als konstante Referenz: könnte der Zugriff auf
std::vector<B>
(die möglicherweise von einer ausführbaren Datei erstellt wurde, die mit einem anderen Compiler (-version) kompiliert wurde) führen zu Problemen inmyFunction
? Ich denke, ja wieder. -
Ist der letzte oben genannte Punkt wirklich die einzige saubere Lösung?
Vielen Dank im Voraus für Ihr Feedback.
0 Stimmen
Der folgende Thread behandelt einige/verwandte Fragen, aber nicht alle Gewinde
0 Stimmen
Template class EXPORT std::vector<B>; funktioniert, um alle Mitgliedsfunktionen richtig zu exportieren/importieren. Was ist mit Template-Funktionen, die keine Member-Funktionen sind? Z.B. operator==()? Beginnend mit VS 2012, erhalte ich jetzt Verknüpfungsfehler beim Erstellen der DLL, weil die Vektorvergleichsfunktion undefiniert ist.
0 Stimmen
Empfohlene weiterführende Lektüre: stackoverflow.com/q/5347355/103167