Dynamische Lib's
-
Hey Leute.
Habe in den FAQ gekuckt, aber nur etwa zu
einer Shared-Lib (*.so) gefunden. Ich wollte mal nachfrage wie man eine Dynamische Library unter Linux bzw. Unix Systemen erstellt.
In Windows heißen se ja *.dll, unter Unix Systemen einfach nur *.dl oder?Wie sieht für die der Code aus?
Paar Links zu tutrials tun es auch^^Mfg Wikinger75!
-
Nein, unter Linux heißen sie *.so. Shared Libs sind das gleiche wie dynamische Libs.
-
Wikinger75 schrieb:
Wie sieht für die der Code aus?
Für die .so-Dateien muss der Code nicht geändert werden. Sie verhalten sich, wie "normale" Objekt-Dateien.
Wikinger75 schrieb:
Paar Links zu tutrials tun es auch^^
Du könntest z.B. das Autotools-Tutorial im Magazin lesen. Dort ist auch ein Abschnitt über libtool.
-
Hallo Wikinger,
ich empfehle die Verwendung des version scripts:
Linker Option --version-scriptIm version script definiert man dann die exportierenden Funktionen.
So ist das Interface der *.so genau defiert und es kommt nicht zu Überraschungen.
Mit version Script verhalten sich die *.so von linux wie die *.dll von windows.Noch etwas (so oder dll):
ich empfehle im Interface (*.h Dateien) auf Strukturen und Klassen verzichten.
Auch würde ich auf Implementieren im Interface (inline, ...) verzichten.Kurz:
Ich würde nach wie vor eine klassische C-Api mit int, long, float und Pointern (auf z.B. vorwärts deklarierte Strukturen) verweden.
Alles andere kann beliebige Runtime Probleme beim Austausch der so/dll verursachen.Gruß Frank
-
der code selbst bleibt gleich, muss aber mit der option -fPIC compiliert werden.
Frank Erdorf schrieb:
ich empfehle im Interface (*.h Dateien) auf Strukturen und Klassen verzichten.
Auch würde ich auf Implementieren im Interface (inline, ...) verzichten.Kurz:
Ich würde nach wie vor eine klassische C-Api mit int, long, float und Pointern (auf z.B. vorwärts deklarierte Strukturen) verweden.
Alles andere kann beliebige Runtime Probleme beim Austausch der so/dll verursachen.bitte führ das etwas aus. ich muss mich sehr zurückhalten, um nicht mit meiner meinung über diese aussagen herauszuplatzen, da ich echt niemanden beleidigen will. die aussagen bezüglich des inline und des version script sind die einzig sinnvollen, wobei letzteres nicht wirklich wichtig ist für linux. das wäre perfektionismus, der auch ohne version script leichter zu erreichen wäre.
-
Frank Erdorf schrieb:
Noch etwas (so oder dll):
ich empfehle im Interface (*.h Dateien) auf Strukturen und Klassen verzichten.
Auch würde ich auf Implementieren im Interface (inline, ...) verzichten.Kurz:
Ich würde nach wie vor eine klassische C-Api mit int, long, float und Pointern (auf z.B. vorwärts deklarierte Strukturen) verweden.
Alles andere kann beliebige Runtime Probleme beim Austausch der so/dll verursachen.Dank der ABI ist es unter Linux eigentlich gar kein Problem, Strukturen und Klassen im Interface einer so anzubieten. Das ist eben anders unter Windows, wo jeder Compilerhersteller seine eigene Suppe kocht.
-
Hallo besserwisser,
Das Problem ist das wenn man Strukturen und Klassen im dll Header (windows oder Linux) deklariert, diese in der Regel z.B. auch im Hauptprogramm verwendet werden.
Aber es ist und bleibt linken (hier dynamisch) und deshalb gibt es folgendes Problem:
Im Hauptprogramm wurde Speicher für die Struktur Klasse reserviert.
Das wurde entweder auf dem Stack oder auf dem Heap gemacht.
Und zwar genau so viel Speicher wie zur Compilezeit des Hauptprogrammes zu erwarten war.Will man nun eine neue Version der dll bauen und z.B. eine Struktur im Header erweitern so MUSS man das Hauptprogramm neu compilieren, linken und bauen
und zwar gegen die neuen Header der dll.Mach man das nicht, tauscht z.B. nur die DLL aus,
gibt es fürchterliche Laufzeitfehler, Speicher Oberschreiber, ...
übrigends ohne einen Hinweis vom compiler linker, ...Richtig 'nett' wird es wenn man Klassen hat, Vererbung, die Reihenfolge
von Methoden ändert und die dll austauscht ohne das Hauptprogramm neu zu bauen.
Dann werden sogar komplett falsche Methoden angesprungen.Kurz:
verwendet man Strukturen oder Klassen,
so MUSS man bei bestimmten Änderungen am Interface auch das/oder die Hauptprogramme neu linken.
Das widerspricht in diesem Punkt meiner Auffassung von dlls.
Deswegen verwende ich so denn möglich eine klassische c api als Interface.
Hinter der Api verwende ich in der dll vollständiges c++.Ich hoffe das klärt die Sache ein wenig,
das ganze ist kein einfaches Thema und nicht mal eben diskutiert.
Es gibt auch noch weitere Gründe für meine Empfehlung.Gruß Frank
-
Hallo rüdiger
was ist "ABI"
Danke Frank
-
Manchmal ein Schulabschluss, manchmal aber auch: http://en.wikipedia.org/wiki/Application_binary_interface
-
Man sollte keine Implementationsdetails in die Header packen, wenn man eine dynamische Library anbieten will. Aber das spricht nicht generell gegen Klassen oder Strukturen. Mit dem PIMPL-Idiom kann man diese Implementationsdetails aber schön vom Header trennen. Daher würde ich mich nicht generell gegen Klassen/Strukturen im Header aussprechen.
-
Hallo Rüdiger,
Es ist richtig,
ein vorwärts deklarierter Pointer: pImpl ist schon der bessere Ansatz.
Löst aber nicht alle möglichen Probleme bei Erweiterungen.Es gibt auch noch einen darüber hinausgehenden Ansatz 'CImpl'.
Hier deklariert man eine rein virtuelle Basisklasse als dll/so Interface.
Die Construktoren der Objekte sind private.
Die Objekte können nur über Factories generiert werden.
Die Factories liefern Pointer oder shared pointer.
Löst aber auch nicht alle möglichen Probleme bei Erweiterungen.Die klasssiche dll/so c-api ohne Strukturen lässt einzig alle Freiheitsgrade
bei Erweiterungen. Hier kann man wirklich dynamisch (loadLibrary, dlOpen, ...) linken. Hiermit kann man sogar für Kreuz Kompatiblität sorgen:altes Progemm läuft mit alter DLL
neues Progemm läuft mit alter DLL
altes Progemm läuft mit neuer DLL
neues Progemm läuft mit neuer DLLWobei nur im letzen Fall volle neue Funktionalität möglich ist.
In allen anderen Fällen erhält man aber volle alte Funktionalität
und keine komische Effekte oder Fehler vom dynamischen Linker!Ich bleibe dabei, wann immer möglich verwende ich für dll/so eine
alte c-api ohne Strukturen in den Header.Komplexe Objekte werden in der dll/so über (c) Factories erzeugt.
Es werden nur Pointer (handles) auf diese Objekte herausgegeben.
Die rausgegebenen Pointer werden in ein oder mehreren statischen Listen gehalten, so können diese in der dll/so immer auf Gültigkeit geprüft werden.Der Aufwand für das Interface ist zwar etwas höher rechnet sich
alleine schon wegen der geringeren Fehlermöglichkeiten.Gruß Frank