Exportierte Symbole in .dll und header Datei Organistation
-
Angenommen ich habe eine shared library (.dll), welche 2 Funktionen zur Verfügung stellen soll:
* quadriere(double foo)
* bestimmeWetter(MeineDatumKlasse *foo)bestimmeWetter ist allerdings eine komplexe Funktion, die mehrere Hilfsfunktionen aufruft um ihre Berechnungen anzustellen. Diese sollen aber nicht als Symbole außerhalb der .dll zur Verfügung stehen.
Was ist gängige Praxis in so einer Situation?
Nimmt man verschiedene Header, einmal mit Hilfsfunktionen und einmal ohne? (Die Symbole stehen dann aber trotzdem in der .dll und könnten über so etwas wie dependancy walker ausgelesen werden)
Deklariert man sie garnicht und schreibt sie in einen namenlosen namespace? (Wodurch man sie nur in einer Datei nutzen kann, was irgendwie ungünstig ist)
Gibt es in C++ so etwas wie einen 'exportiere diese Symbole nicht' Befehl? Falls ja, wie sieht dann ein zur Bibliothek passender header aus?
Wenn mich jemand aufklären könnte oder mir sagen kann nach was ich suchen muss wäre das super :).
-
Was juckt es dich, ob die Symbole mit dem Dependency Walker zu sehen sind?
Grundsätzlich gibt es in Bibliotheken öffentliche und private Header. Bei einer Auslieferung ohne Sourcecode legt man nur die öffentlichen bei.
Funktionen aus Windows-DLLs kann man nur binden, wenn sie mit dllexport im Header exportiert wurden.
-
Hi,
für interne Hilfsfunktionen verwenden viele Projekte separate Header, in denen nur die internen Funktionen und Symbole deklariert werden. Diese haben teilweise ein "priv_" oder "private_" Präfix/Suffix oder befinden sich in einem "private"/"internal"/"detail"-Unterverzeichnis. Diese Header werden dann üblicherweise auch nicht zusammen mit der Bibliothek "installiert", landen also nicht im include-Verzeichnis des Anwenders der Bibliothek sondern werden lediglich beim Kompilieren der Bibliothek eingebunden.
Ich selbst lege solche internen Header meist direkt zusammen mit den
.cpp-Dateien im "source"-Verzeichnis der Bibliothek ab und nicht im "include"-Geschwisterverzeichnis (dort packe ich nur die öffentlichen Header rein). Das sieht dann in etwa so aus:[include] mylibrary.hpp [source] fancyfunction.cpp helper.cpp helper.hppEinen wirklichen Standard gibt es da nicht, lass dich am besten von ein paar Open Source-Projekten inspirieren und such dir was passendes aus, was du für sinnvoll erachtest.
Was die Sichtbarkeit von Symbolen in der DLL angeht: Mit Visual Studio muss man Symbole mit
__declspec(dllexport)explizit für den Export markieren. Wenn du das für die internen Funktionen weglässt, sollten diese in der DLL auch nicht mehr sichtbar sein (können aber trotzdem intern verwendet werden).Bei GCC sind alle Symbole per default sichtbar (werden von der DLL exportiert), soweit ich weiss lässt sich das aber mit dem compilerspezifischen Attribut
__attribute__ ((visibility "hidden")))für einzelne Symbole deaktivieren. Das sollte dann eigentlich den selben Effekt haben wie unter MSVC__declspec(dllexport)wegzulassen.Gruss,
Finnegan
-
Ich war bisher (aus welchen Gründen auch immer) der Meinung, dass grundsätzlich alle Symbole immer sichtbar sind. Das mit __declspec(dllexport) kommt mir also echt entgegen.
Der Hintergrund ist einfach der, dass ich nach außen ein sauberes Interface präsentieren will. Welche Funktionen dann letztendlich wie intern voneinander abhängen kann ich dann nach belieben verändern ohne Angst haben zu müssen, dass irgendein Genie genau diese Funktion in seinem Programm benuzt.
Danke für die schnelle Antwort

-
FirefoxMetzger schrieb:
Der Hintergrund ist einfach der, dass ich nach außen ein sauberes Interface präsentieren will. Welche Funktionen dann letztendlich wie intern voneinander abhängen kann ich dann nach belieben verändern ohne Angst haben zu müssen, dass irgendein Genie genau diese Funktion in seinem Programm benuzt.
Prinzipiell ein Ansatz, den ich auch bevorzugen würde, allerdings halte ich die Wahrscheinlichkeit, dass das tatsächlich passiert für extrem gering, solange man die internen Funktionen nicht über den öffentlichen Header exponiert.
Ich glaube mit sowas muss man erst rechnen wenn man an einer weit verbreiteten proprietären API arbeitet (ich denke da z.B. an diverse undokumentierten Funktionen der Windows-API - habe gerade kürzlich einen Vortrag über
Race Conditions bei Dateisystemzugriffen gesehen, bei der eine besonders effizente Lösung eine solche Funktion benötigte).
Bei einer gewöhnlichen Bibliothek wird wohl kaum einer auf die abstruse Idee kommen solche internen Funktionen zu verwenden. Und falls doch, dann ist denen sowieso nicht mehr zu helfen - mit so einer Grundeinstellung werden
sie sich noch ganz andere Probleme einfangen, auf die man als Bibliotheksentwickler keinen Einfluss mehr hat
Finnegan