Seite 1 von 2

Shared Object / DLL erstellen

Verfasst: 6. Juni 2008 17:36
von chrootdev
Hallo,

ich versuche gerade eine *.so datei unter linux zu erstellen. Ich arbeite mit eclipse und qt 4.4!

Ich hatte mich an diesem thread http://www.qtforum.de/forum/viewtopic.p ... ib&start=0 orientiert, und zusätzlich an einem buch.

Jedoch verstehe ich einiges noch nicht ganze, bzw funktioniert es nicht was ich mache.

Ich habe nach dem buch die lib wie unten gebaut, und diese soll lediglich eine messagebox aufrufen.

testlib.h

Code: Alles auswählen

#ifndef TESTLIB_H_
#define TESTLIB_H_

#ifdef BUILD_DLL
	#define EXPORT_DLL Q_DECL_EXPORT
#else
	#define EXPORT_DLL
#endif

#include <QtGui>
#include <QObject>

class EXPORT_DLL testlib : public QObject {

	Q_OBJECT

	public:
		testlib() {};
		~testlib() {};
		void printOut();
};

#endif /* TESTLIB_H_ */
testlib.cpp

Code: Alles auswählen

#include "testlib.h"

void testlib::printOut() {
	QMessageBox::information(NULL,QObject::tr("Erfolgreich"),QObject::tr("Dynamische Bibliothek erfolgreich ausgeführt!"));
}
pro datei

Code: Alles auswählen

TEMPLATE = lib
TARGET = 
DEPENDPATH += .
INCLUDEPATH += .
CONFIG += qt dll thread

# Input
HEADERS += testlib.h
SOURCES += testlib.cpp
Es werden einige dateien erstellt, unter anderem diese:
libtestlib.so
libtestlib.so.1
libtestlib.so.1.0
libtestlib.so.1.0.0

wobei alle bis auf libtestlib.so.1.0.0 links auf diese datei sind!

Wenn ich die datei libtestlib.so.1.0.0 jetzt in ein anderes testprojket kopiere, inkl. header (testlib.h) und diese einbinde und dann das programm starten will, kommt folgende fehlermeldung:

/testapp: error while loading shared libraries: libtestlib.so.1: cannot open shared object file: No such file or directory
Könnte mir bitte jemand sagen, was ich falsch gemacht habe? Oder hat jemand einen link zu einem kompletten und funktionierenden beispiel für linux? Oder hat jemand direkt ein beispiel?

Danke!

Mfg

Verfasst: 6. Juni 2008 17:41
von jd
Hallo, du hast nichts falsch gemacht, bei der stimmt nur der "Lagerort" der Library nicht. Kopier die mal nach /usr/lib/ und schon müsste es gehen.

Alternativ kannst du auch den LD_LIBRARY_PATH verbiegen. Hier ist mal ein Statup-Skript für ein Programm, was mitgebrachte libs nutzt.

Pack das in den selben Ordner wo die ausführbare Datei ist, um das Programm zu starten.

Code: Alles auswählen

#!/bin/sh
LD_LIBRARY_PATH=$PWD/libs
export LD_LIBRARY_PATH
$PWD/dein_programm

Verfasst: 6. Juni 2008 18:01
von chrootdev
Hallo,

danke für deine antwort!

Ich habe jetzt ein shell script mit deinen angaben gemacht, und die datei "libtestlib.so.1.0.0" und die header datei "testlib.h" in den ordner "<programmordner>/libs" kopiert, leider bekomme ich die selbe fehlermeldung.

Was ich vorhin vergessen habe, ich habe die datei "libtestlib.so.1.0.0" in der pro datei des testprogrammes das die lib verwenden soll angegeben:

Code: Alles auswählen

TEMPLATE = app
TARGET = 
DEPENDPATH += .
INCLUDEPATH += .

# Input
HEADERS += libs/testlib.h
SOURCES += main.cpp
LIBS += libs/libtestlib.so.1.0.0
Die lib heisst "libtestlib.so.1.0.0" jedoch kommt bei der fehlermeldung "libtestlib.so.1", warum?


//EDIT: Hat schon funktioniert, ich musste einfach nur die datei auf "libtestlib.so.1" umbenennen.

Danke!

//EDIT: Jetzt hätte ich trotzdem noch gerne gewusst, warum ich die lib im verzeichnis "<programmordner>/libs/" und im verzeichnis "/usr/lib" haben muss damit das programm funktioniert?

Verfasst: 6. Juni 2008 20:13
von jd
Hallo,

das musst du nicht. wenn du den LD_LIBRARY_PATH richtig exportierst, dann passt das. Eine lib besteht immer aus der Main-Datei und den Softlinks.

Geh mal in das Verzeichnis "<programmordner>/libs"

Da hast du eine Datei libtestlib.so.1.0.0 dort müssen auch die Softlinks sein, schau mal wo die hin linken. Falls du dir nicht sicher bist, lege sie neu an mit:

Code: Alles auswählen

ln -s libtestlib.so.1.0.0 libtestlib.so.1.0
ln -s libtestlib.so.1.0.0 libtestlib.so.1
ln -s libtestlib.so.1.0.0 libtestlib.so
Danach exportiere den LD_LIBRARY_PATH noch einmal.

so long[/code]

Verfasst: 8. Juni 2008 15:00
von chrootdev
Hallo,

danke für deine antwort, aber so ganz klar ist mir das immer noch nicht.

Ich erklär kurz mein vorgehen, und zwar:

Ich habe die *.so datei erstellt, "libtestlib.so.1.0.0" dabei wurden auch noch links auf die datei erstellt (libtestlib.so, libtestlib.so.1, libtestlib.so.1.0). Jetzt möchte ich die datei "libtestlib.so.1.0.0" fix in meinem programm verwenden, also nicht dynamisch zur laufzeit.

Dabei habe ich in der *.pro datei des anderen testprogrammes (testapp) die lib angegeben und zwar mit "LIBS += libs/libtestlib.so.1.0.0".

Warum sucht das programm die lib aber immer noch unter "/usr/lib", wenn ich sie explizit angegeben habe?

Danke!

Verfasst: 8. Juni 2008 15:04
von PeterLustig
Hast du in der Dokumentation mal das "LIBS" angeschaut?

Verfasst: 8. Juni 2008 15:58
von chrootdev
Hallo,

meinst du speziell das hier?
Declaring Other Libraries

If you are using other libraries in your project in addition to those supplied with Qt, you need to specify them in your project file.

The paths that qmake searches for libraries and the specific libraries to link against can be added to the list of values in the LIBS variable. The paths to the libraries themselves can be given, or the familiar Unix-style notation for specifying libraries and paths can be used if preferred.

For example, the following lines show how a library can be specified:

LIBS += -L/usr/local/lib -lmath

The paths containing header files can also be specified in a similar way using the INCLUDEPATH variable.

For example, it is possible to add several paths to be searched for header files:

INCLUDEPATH = c:/msdev/include d:/stl/include
Wenn dem so ist, muss ich also meine eigenen libs mit "LIBS += -L" angeben, aber in dem beispiel wird ein pfad statisch angegeben. Wie gebe ich den dynamisch zu meinem projekt an? Gibts da irgendeine methode?

Code: Alles auswählen

LIBS += <projektverzeichnis>/libs/libtestlib.so.1
Danke!

Verfasst: 9. Juni 2008 15:06
von chrootdev
Nach weiterem stöbern im forum, und lesen der doku, habe ich etwas gefunden, und zwar:

Würde das funktionieren?

Code: Alles auswählen

LIBS += $$(PWD)/libs/libtestlib.so.1
Würde das unter linux sowie windows funktionieren?

Danke!

Verfasst: 9. Juni 2008 15:21
von jd
Unter Windows ehr weniger da PWD eine globale von Linux ist dir das aktuelle Verzeichnis gibt, wo du dich gerade befindest. Außerdem weiß ich nicht wo dein Problem ist. Es wurde ja schon erwähnt wie man das mit dem .pro file macht... und wo Linux nach libs sucht und wie man das umbiegen kann, daher verstehe ich dein Problem nicht.

Verfasst: 9. Juni 2008 15:35
von chrootdev
jd hat geschrieben:daher verstehe ich dein Problem nicht.
Mein problem ist ganz einfach das ich in meinem anwendungsverzeichnis in einem verzeichnis darunter (/libs) alle benötigten libs speichern möchte, und das qt nicht unter "/usr/libs" danach sucht, sondern primär in dem von mir angegebenen verzeichnis.
jd hat geschrieben:Es wurde ja schon erwähnt wie man das mit dem .pro file macht... und wo Linux nach libs sucht und wie man das umbiegen kann,[...]
Ja, danke, das hat mich auch weiter gebracht, nur würde ich gern das programm starten ohne vorher mit einem shellscript irgendwas zu verbiegen!

Einfach: Programm(.exe) doppel klicken, und spass haben!

Geht das, so wie ich es mir vorstelle oder nicht?

Wie würdest/machst du das? Sonst muss man ja das programm über das shellscript starten, und das will ich nicht!

Verfasst: 9. Juni 2008 15:44
von jd
He :) das gleiche Problem hatte ich auch. Es ist an sich ganz einfach. /usr/lib ist Standard, alle Paketsysteme (apt, rpm, etc) greifen darauf zu. Wenn du jetzt deine Libs unter /home/user/program/libs/ haben willst, bist du der Exot :) sprich Linux muss sich nicht an dich Anpassen sonder du dich an Linux so ist das nun mal du verstößt da gegen einen Standard der seit Jahren existiert. Also musst du das ganze aus hebeln, mit einem Shell-Script.

Unter Windows bin ich da der falsche Ansprechpartner, weil ich mich mit Windows nicht wirklich aus kenne und ich nur Linux nutze. Aber da läuft das ähnlich... Bei Windows gibt es auch Umgebungsvariablen. Du hast da auch wieder 2 Möglichkeiten.. 1. Hau alles unter C:\windows\system32 rein, oder hau alles in den gleich Ordner wo deine Ausführbare Programmdatei ist.

Das mit dem .pro-file hast du glaube ich missverstanden. LIBS im Pro-file sagt nur aus wo die Lib ist, damit kompiliert werden kann. Das hat nicht mit der Ausführung des Programms zu tun, denn da greift wieder das jeweilige OS ein.

Hoffe das hilft dir etwas.

so long
jd

Verfasst: 9. Juni 2008 15:59
von chrootdev
jd hat geschrieben:Unter Windows bin ich da der falsche Ansprechpartner, [...]
Danke, bin auch linux nutzer! Wenn das programm auch auf windows läuft wäre das ein netter bonus, aber nicht zwingend notwendig.
Das mit dem .pro-file hast du glaube ich missverstanden. LIBS im Pro-file sagt nur aus wo die Lib ist, damit kompiliert werden kann. Das hat nicht mit der Ausführung des Programms zu tun, denn da greift wieder das jeweilige OS ein.

Hoffe das hilft dir etwas.
Mehr oder weniger.

Soll das heißen, wenn ich jetzt auf meinem rechner kompiliere, und dann einfach die ausführbare datei weitergebe (ohne die lib) läuft das programm trotzdem, da es ja schon kompiliert wurde?

Danke!

Verfasst: 9. Juni 2008 16:20
von jd
chrootdev hat geschrieben:Wenn das programm auch auf windows läuft wäre das ein netter bonus, aber nicht zwingend notwendig.
Ist bei mir auch so :)

Ja du kannst deine ausführbare Datei weitergeben. Der die dann ausführen will, muss nur prüfen ob die Qt-libs vorhanden sind. Sprich er benötigt genau das, was du auch zum kompilieren benötigt hast. Ich verwende Debian, da wäre:

Code: Alles auswählen

apt-get install libqt4-dev
Dann könnte ich deine ausführbare Datei starten.
libqt4-dev(el) haut dir einfach alle libs unter /usr/lib, kannst selber schauen.

Code: Alles auswählen

ls -al /usr/lib/libQt*
Um sowas zu umgehen liefert man die Qt-Libs mit oder man gibt ein Paket raus, was man mit ./configure; make; make install bauen muss, oder man hält sich an das Paketsystem und baut gescheite debs; rpms. Kommt eigentlich auf selbe raus.

Wenn du dir mal was komplettes ansehen willst (source-code und binary lösung). Schick mir ne PN dann kann ich dir mal was geben (wie ich das gemacht habe) Für Linux und Win.

Verfasst: 9. Juni 2008 16:21
von RHBaum
Soll das heißen, wenn ich jetzt auf meinem rechner kompiliere, und dann einfach die ausführbare datei weitergebe (ohne die lib) läuft das programm trotzdem, da es ja schon kompiliert wurde?
http://www.yolinux.com/TUTORIALS/Librar ... namic.html

unter windows, rein vom system her, geht version 2.1 nicht !
windows kann nur 100% statisch (linker), und 100% dynamisch (LoadLibrary)
dann gibts noch die kruecke zwischendrin, beim erstellen der Dll wird dir ne dll und eine sogenannte export lib erstellt, das ist wirklich ne statische lib, die dir alle symbole exportiert, und die lib quasi statisch, also noch vor funktionseintritt in die main() die bib laed.
Hat den selben effekt wie 2.1 unter linux, nur das wirklich dem linker ne .lib (aquivalent zu .a wenn nicht den gcc port nimmst) zum statischen linken gibst. Mit dem vorteil, das der teil den zum linken brauchst getrennt ist von dem teil, den zur laufzeit brauchst ...


Setzt dich mal mit deinen make tools auseinander !
Irgendwo hat er doch den pfad wo er dein binary hinkompiliert oder ?
du kompilierst doch ned unter /usr/bin was unter linux scho konsequent waer oder ? dann wuerde deine version mit dem Programmverzeichniss und lib unterverzeichniss soweiso ned funktionieren !

Fuer statisches linken waer eh nen unterverzeichniss im Buildverzeichniss die erste wahl.

unter linux nen programmverzeichniss ? glaub das ist eher nen exot ....
schoen nach /usr/bin das binary und die dynamischen libs nach /usr/lib/programmname, oder /opt/share/programmname/plugins oder sowas, je nachdem was die lib darstellen soll ...
http://en.wikipedia.org/wiki/Filesystem ... y_Standard


Ciao ...

Verfasst: 9. Juni 2008 16:30
von jd
Unter Linux gibt es keine Programm Verzeichnisse das ist eine überflüssige Erfindung von Windows. Unter Linux gibt es "Programm-Parts" Binary, Lib, Man, Images,

Binary: /usr/bin
Lib: /urs/lib
man: /usr/share/man
images: /usr/share/pixmaps
other: /usr/share/apps/

Linken für Desktop und Startmenu: /usr/share/applications/

So installiert man Linux Programme richtig. Da passt alles 100% in das System Bilder werden gefunden etc. So machen es auch die Paketsysteme und so macht es auch ein ./configure; make; make install;