lib programmieren
lib programmieren
Moin Moin! <img src="http://www.pl-forum.de/UltraBoard/Images/Happy.gif" border="0" align="middle">
Sagt mal, gibt es irgendwo ein HowTo, in dem einfach beschrieben steht, wie man eine eigene Lib programmiert und diese (logischerweise) auch in eigene, externe Programme einbindet?
Ich hab mal eine unter dem guten alten Amiga erstellt, aber das ist ja schon ewigkeiten her ...
Spezielle geht es mir darum, genaue Einsprungfunktionen zu definieren, die ich von extern nutzen kann und (natürlcih) die lib erstmal zum laufen zu bewegen
Bodo
Sagt mal, gibt es irgendwo ein HowTo, in dem einfach beschrieben steht, wie man eine eigene Lib programmiert und diese (logischerweise) auch in eigene, externe Programme einbindet?
Ich hab mal eine unter dem guten alten Amiga erstellt, aber das ist ja schon ewigkeiten her ...
Spezielle geht es mir darum, genaue Einsprungfunktionen zu definieren, die ich von extern nutzen kann und (natürlcih) die lib erstmal zum laufen zu bewegen
Bodo
Re: lib programmieren
Folgendes Beispiel, eine (shared) lib mit nur einer Funktion:
/* Anfang test.c */
#include <stdio.h>
void hellow(void)
{
printf("Hello World
");
}
/* Ende test.c */
/* Anfang test.h */
void hellow(void);
/* Ende test.h */
gcc -c test.c
gcc -shared -o libtestlib.so test.o
So, jetzt wirds spannend <img src="http://www.pl-forum.de/UltraBoard/Images/Happy.gif" border="0" align="middle">.
/* Anfang libtest.c */
#include "test.h"
int main()
{
hellow(); /* Aus unserer lib */
return 0;
}
/* Ende libtest.c */
gcc -L. -o libtest libtest.c -ltestlib
export LD_LIBRARY_PATH=$PWD
./libtest
Hello World
In der Tat, es geht. Ich hoffe du konntest diese Schritte nachvollziehen...
/* Anfang test.c */
#include <stdio.h>
void hellow(void)
{
printf("Hello World
");
}
/* Ende test.c */
/* Anfang test.h */
void hellow(void);
/* Ende test.h */
gcc -c test.c
gcc -shared -o libtestlib.so test.o
So, jetzt wirds spannend <img src="http://www.pl-forum.de/UltraBoard/Images/Happy.gif" border="0" align="middle">.
/* Anfang libtest.c */
#include "test.h"
int main()
{
hellow(); /* Aus unserer lib */
return 0;
}
/* Ende libtest.c */
gcc -L. -o libtest libtest.c -ltestlib
export LD_LIBRARY_PATH=$PWD
./libtest
Hello World
In der Tat, es geht. Ich hoffe du konntest diese Schritte nachvollziehen...
Re: lib programmieren
Danke!! <img src="http://www.pl-forum.de/UltraBoard/Images/Happy.gif" border="0" align="middle">
Ich probiers gleich mal, wenn ich wieder zu Hause bin und diese dämliche Migräne los bin!
Bodo
Ich probiers gleich mal, wenn ich wieder zu Hause bin und diese dämliche Migräne los bin!
Bodo
Re: lib programmieren
Hi,
wow, das hab ich auch kapiert. Sollte ich vielleicht auch mal ausprobieren.
cu
Oliver
wow, das hab ich auch kapiert. Sollte ich vielleicht auch mal ausprobieren.
cu
Oliver
Re: lib programmieren
Hi!
Ich bin jetzt ein wenig verwirrt, denn ich dachte, für Bibliotheken müsste man PIC (Position Independent Code) verwenden, wozu man die Option -fPIC angeben muss. Ok, ich habe in die gcc-Doku geschaut und in der Tat scheint man PIC nicht zwingend zu benötigen, aber dann frage ich mich, was die Vor-/Nachteile von PIC sind. Weiß jemand etwas darüber?
Cheers,
Wolfgang
Ich bin jetzt ein wenig verwirrt, denn ich dachte, für Bibliotheken müsste man PIC (Position Independent Code) verwenden, wozu man die Option -fPIC angeben muss. Ok, ich habe in die gcc-Doku geschaut und in der Tat scheint man PIC nicht zwingend zu benötigen, aber dann frage ich mich, was die Vor-/Nachteile von PIC sind. Weiß jemand etwas darüber?
Cheers,
Wolfgang
Re: lib programmieren
<a href="http://mail.gnu.org/pipermail/libtool/1 ... 03566.html" target="_blank"><!--auto-->http://mail.gnu.org/pipermail/libtool/1 ... <!--auto-->
<blockquote><hr>
> I have to admit that it makes perfect sense to me that you can't link
> non-pic object files in what will become a shared object file. I mean,
> if you could, there would be no need for the -fPIC option.
> Generally, non-pic code is faster than pic code anyway.
> Why would anybody use -fPIC if it's not needed for a shared object?
In an executable, non-pic code is faster. However, a shared library
needs to be position independent. You can build a shared library with
non-pic code, but that just means that the dynamic linker has to do
much more work to load the code at whatever address it should go to.
Specifically, the dynamic linker has to resolve all the relocations at
run time, every time the program is run. Thus, in a shared library,
pic code is faster. That's why pic code was invented.
> I mean, if you could, there would be no need for the -fPIC option.
> Generally, non-pic code is faster than pic code anyway. Why would
> anybody use -fPIC if it's not needed for a shared object?
A good reason I can think of is that relocation would prevent code
pages from being shared, if they happen to be mapped onto different
addresses in different processes' address spaces.
<hr></blockquote>
<blockquote><hr>
> I have to admit that it makes perfect sense to me that you can't link
> non-pic object files in what will become a shared object file. I mean,
> if you could, there would be no need for the -fPIC option.
> Generally, non-pic code is faster than pic code anyway.
> Why would anybody use -fPIC if it's not needed for a shared object?
In an executable, non-pic code is faster. However, a shared library
needs to be position independent. You can build a shared library with
non-pic code, but that just means that the dynamic linker has to do
much more work to load the code at whatever address it should go to.
Specifically, the dynamic linker has to resolve all the relocations at
run time, every time the program is run. Thus, in a shared library,
pic code is faster. That's why pic code was invented.
> I mean, if you could, there would be no need for the -fPIC option.
> Generally, non-pic code is faster than pic code anyway. Why would
> anybody use -fPIC if it's not needed for a shared object?
A good reason I can think of is that relocation would prevent code
pages from being shared, if they happen to be mapped onto different
addresses in different processes' address spaces.
<hr></blockquote>
Re: lib programmieren
Auf manchen Plattformen scheint es möglich zu sein, funktionierende shared libraries auch ohne die Compiler-Option -fPIC zu erzeugen. Mindestens auf der ARM Plattform funktioniert ein solches vorgehen allerdings anscheinend nicht.
Da aber die Programming-Library-HOWTO schreibt, dass man zum erzeugen einer shared library den Library Quellcode mit <b>gcc -fPIC -c test.c</b> kompilieren und mit <b>gcc -shared -o libtestlib.so test.o</b> linken soll, denke ich einfach mal dass dies die korrektere Vorgehensweise ist.
How to build libraries?
<a href="http://lists.samba.org/pipermail/linux/ ... 00318.html" target="_blank"><!--auto-->http://lists.samba.org/pipermail/linux/ ... <!--auto-->
[<!--no-->ARM<!--no-->] about shared libraries
<a href="http://lists.arm.linux.org.uk/pipermail ... 00221.html" target="_blank"><!--auto-->http://lists.arm.linux.org.uk/pipermail ... <!--auto-->
Program-Library-HOWTO
<a href="http://www.linuxdoc.org/HOWTO/Program-L ... html#AEN79" target="_blank"><!--auto-->http://www.linuxdoc.org/HOWTO/Program-L ... <!--auto-->
Da aber die Programming-Library-HOWTO schreibt, dass man zum erzeugen einer shared library den Library Quellcode mit <b>gcc -fPIC -c test.c</b> kompilieren und mit <b>gcc -shared -o libtestlib.so test.o</b> linken soll, denke ich einfach mal dass dies die korrektere Vorgehensweise ist.
How to build libraries?
<a href="http://lists.samba.org/pipermail/linux/ ... 00318.html" target="_blank"><!--auto-->http://lists.samba.org/pipermail/linux/ ... <!--auto-->
[<!--no-->ARM<!--no-->] about shared libraries
<a href="http://lists.arm.linux.org.uk/pipermail ... 00221.html" target="_blank"><!--auto-->http://lists.arm.linux.org.uk/pipermail ... <!--auto-->
Program-Library-HOWTO
<a href="http://www.linuxdoc.org/HOWTO/Program-L ... html#AEN79" target="_blank"><!--auto-->http://www.linuxdoc.org/HOWTO/Program-L ... <!--auto-->
Re: lib programmieren
Hi!
Vielen Dank für die Erklärung, und natürlich auch für die Links.
Cheers,
Wolfgang
Vielen Dank für die Erklärung, und natürlich auch für die Links.
Cheers,
Wolfgang
Re: lib programmieren
<font size="4">Quellcodes</font><!--4--> wie bereits oben geposted.
<font size="3">test.c</font><!--3--><font face="Courier New">
// Quellcode unserer Lib
void hellow(void)
{
printf("Hello World\<!--no-->n");
}
</font><!--fixed-->
<font size="3">test.h</font><!--3--><font face="Courier New">
// liste der exportierten funktionen
void hellow(void);
</font><!--fixed-->
<font size="3">libtest.c </font><!--3--><font face="Courier New">
// testprogramm fuer unsere library
#include "test.h"
int main(int argc, char** argv)
{
hellow(); /* Aus unserer lib */
return 0;
}
</font><!--fixed-->
<font size="4">shared library:</font><!--4-->
<font size="3">Lib erstellen:</font><!--3-->
<font size="2">Linux:</font><!--2--><font face="Courier New">
$ gcc -fPIC -DPIC -c test.c
$ gcc -shared -o libtestlib.so.1.0 -Wl,-soname,libtestlib.so.1 test.o
$ ln -s libfoo.so.1.0 libfoo.so.1
$ ln -s libfoo.so.1 libfoo.so</font><!--fixed-->
<font size="2">Solaris:</font><!--2--><font face="Courier New">
$ gcc -fPIC -DPIC -c test.c
$ ld -G -o libtestlib.so test.o</font><!--fixed-->
<font size="2">Irix:</font><!--2--><font face="Courier New">
$ gcc -fPIC -DPIC -c test.c
$ ld -shared -o libtestlib.so test.o</font><!--fixed-->
<font size="3">Lib benutzen:</font><!--3--><font face="Courier New">
$ export LD_LIBRARY_PATH=.:${LD_LIBRARY_PATH}
$ gcc -L. -o libtest libtest.c -ltestlib</font><!--fixed-->
<font size="4">static library:</font><!--4-->
<font size="3">Lib erstellen:</font><!--3--><font face="Courier New">
$ gcc -fPIC -DPIC -c test.c
$ ar rcs libtest-static.a test.o</font><!--fixed-->
<font size="3">Lib benutzen:</font><!--3--><font face="Courier New">
$ gcc -L. -o libtest libtest.c -ltestlib-static</font><!--fixed-->
<font size="4">Referenz:</font><!--4-->
Program-Library-HOWTO
<a href="http://www.linuxdoc.org/HOWTO/Program-L ... html#AEN79" target="_blank"><!--auto-->http://www.linuxdoc.org/HOWTO/Program-L ... <!--auto-->
<font size="3">test.c</font><!--3--><font face="Courier New">
// Quellcode unserer Lib
void hellow(void)
{
printf("Hello World\<!--no-->n");
}
</font><!--fixed-->
<font size="3">test.h</font><!--3--><font face="Courier New">
// liste der exportierten funktionen
void hellow(void);
</font><!--fixed-->
<font size="3">libtest.c </font><!--3--><font face="Courier New">
// testprogramm fuer unsere library
#include "test.h"
int main(int argc, char** argv)
{
hellow(); /* Aus unserer lib */
return 0;
}
</font><!--fixed-->
<font size="4">shared library:</font><!--4-->
<font size="3">Lib erstellen:</font><!--3-->
<font size="2">Linux:</font><!--2--><font face="Courier New">
$ gcc -fPIC -DPIC -c test.c
$ gcc -shared -o libtestlib.so.1.0 -Wl,-soname,libtestlib.so.1 test.o
$ ln -s libfoo.so.1.0 libfoo.so.1
$ ln -s libfoo.so.1 libfoo.so</font><!--fixed-->
<font size="2">Solaris:</font><!--2--><font face="Courier New">
$ gcc -fPIC -DPIC -c test.c
$ ld -G -o libtestlib.so test.o</font><!--fixed-->
<font size="2">Irix:</font><!--2--><font face="Courier New">
$ gcc -fPIC -DPIC -c test.c
$ ld -shared -o libtestlib.so test.o</font><!--fixed-->
<font size="3">Lib benutzen:</font><!--3--><font face="Courier New">
$ export LD_LIBRARY_PATH=.:${LD_LIBRARY_PATH}
$ gcc -L. -o libtest libtest.c -ltestlib</font><!--fixed-->
<font size="4">static library:</font><!--4-->
<font size="3">Lib erstellen:</font><!--3--><font face="Courier New">
$ gcc -fPIC -DPIC -c test.c
$ ar rcs libtest-static.a test.o</font><!--fixed-->
<font size="3">Lib benutzen:</font><!--3--><font face="Courier New">
$ gcc -L. -o libtest libtest.c -ltestlib-static</font><!--fixed-->
<font size="4">Referenz:</font><!--4-->
Program-Library-HOWTO
<a href="http://www.linuxdoc.org/HOWTO/Program-L ... html#AEN79" target="_blank"><!--auto-->http://www.linuxdoc.org/HOWTO/Program-L ... <!--auto-->
Re: lib programmieren
Also, ich habe mir eine lib erzeugt, was auch wunderbar funktioniert hat. Danke schon mal ...
aaaber ... ich bekomme sie einfach nicht zu meinem testprojekt gelinkt! ((
die einzige Fehlermeldung, die ich erhalte, ist folgende:
/usr/i486-suse-linux/bin/ld: cannot find -lums4sql
collect2: ld returned 1 exit status
und ich habe LD_LIBRARY_PATH entsprechend angepasst ... <img src="http://www.pl-forum.de/UltraBoard/Images/Sad.gif" border="0" align="middle">
hat jemand eine Idee, die mir helfen könnte?
Bodo
aaaber ... ich bekomme sie einfach nicht zu meinem testprojekt gelinkt! ((
die einzige Fehlermeldung, die ich erhalte, ist folgende:
/usr/i486-suse-linux/bin/ld: cannot find -lums4sql
collect2: ld returned 1 exit status
und ich habe LD_LIBRARY_PATH entsprechend angepasst ... <img src="http://www.pl-forum.de/UltraBoard/Images/Sad.gif" border="0" align="middle">
hat jemand eine Idee, die mir helfen könnte?
Bodo
Re: lib programmieren
LD_LIBRARY_PATH muss nur während der Laufzeit gesetzt sein, damit die Library gefunden wird.
Alternativ kann man auch das jeweilige Verzeichnis in die /etc/ld.so.conf eintragen und ein "ldconfig" machen.
Beim compilieren ist es aber einzig und allein wichtig, dass man dem gcc mit der -L-Option das Verzeichnis angibt, wo die eigene Library zu finden ist.
Ich hatte es ja auch in meinem Beispiel so gemacht:
>gcc -L. -o libtest libtest.c -ltestlib
Dabei ist das '-L.' wichtig !
In diesem Fall lag die Library ja im aktuellen Verzeichnis, aber nur durch das '-L.' sucht gcc die Library auch dort.
Ohne das '-L.' hätte ich genau die selbe Fehlermeldung gekrigt wie du jetzt.
Alternativ könntest du die Lib einfach nach /usr/lib kopieren, dann bliebe dir die Angabe der '-L'-Option erspart.
Auch wichtig ist der Name der Library.
Sie muss lib[name].so oder lib[name].a bei einer statischen Library heissen.
Sprich, wenn du '-lums4sql' angibst, muss die Datei libums4sql.so heissen !
Alternativ kann man auch das jeweilige Verzeichnis in die /etc/ld.so.conf eintragen und ein "ldconfig" machen.
Beim compilieren ist es aber einzig und allein wichtig, dass man dem gcc mit der -L-Option das Verzeichnis angibt, wo die eigene Library zu finden ist.
Ich hatte es ja auch in meinem Beispiel so gemacht:
>gcc -L. -o libtest libtest.c -ltestlib
Dabei ist das '-L.' wichtig !
In diesem Fall lag die Library ja im aktuellen Verzeichnis, aber nur durch das '-L.' sucht gcc die Library auch dort.
Ohne das '-L.' hätte ich genau die selbe Fehlermeldung gekrigt wie du jetzt.
Alternativ könntest du die Lib einfach nach /usr/lib kopieren, dann bliebe dir die Angabe der '-L'-Option erspart.
Auch wichtig ist der Name der Library.
Sie muss lib[name].so oder lib[name].a bei einer statischen Library heissen.
Sprich, wenn du '-lums4sql' angibst, muss die Datei libums4sql.so heissen !
Re: lib programmieren
> Auch wichtig ist der Name der Library.
> Sie muss lib[name].so oder lib[name].a bei einer statischen Library heissen.
> Sprich, wenn du '-lums4sql' angibst, muss die Datei libums4sql.so heissen !
Das war schon mal der richtige anhaltspunkt ... damit scheint der erste Fehler verschwunden zu sein ... dafür hab ich jetzt mehr dazu bekommen ;-/
was sagt einem das hier: ??
/tmp/ccqKrcHG.o: In function `main':
/tmp/ccqKrcHG.o(.text+0x6e): undefined reference to `umsLogin(bsString, bsString)'
/tmp/ccqKrcHG.o(.text+0xa9): undefined reference to `umsReadMsg(base *, bsString)'
/tmp/ccqKrcHG.o(.text+0xef): undefined reference to `umsLogout(base *)'
[ diese funktionen will ich aus der lib heraus benutzen ]
./libums4sql.so: undefined reference to `base'
./libums4sql.so: undefined reference to `umsDatabase::disconnect(BASE *)'
./libums4sql.so: undefined reference to `umsQuery::Add(bsString)'
./libums4sql.so: undefined reference to `umsDatabase::umsDatabase(void)'
./libums4sql.so: undefined reference to `umsDatabase::connected(void)'
./libums4sql.so: undefined reference to `umsQuery::Clear(void)'
./libums4sql.so: undefined reference to `BASE::getError(void)'
./libums4sql.so: undefined reference to `BASE::setError(bsString)'
./libums4sql.so: undefined reference to `umsDatabase::connect(void)'
./libums4sql.so: undefined reference to `umsQuery::FieldbyName(bsString)'
./libums4sql.so: undefined reference to `umsQuery::Open(pg_conn *)'
./libums4sql.so: undefined reference to `umsQuery::isEmpty(void)'
./libums4sql.so: undefined reference to `umsDatabase::getLastError(void)'
./libums4sql.so: undefined reference to `umsQuery::umsQuery(void)'
[und das sind Klassen, die ich in der lib intern benutze ...]
> Sie muss lib[name].so oder lib[name].a bei einer statischen Library heissen.
> Sprich, wenn du '-lums4sql' angibst, muss die Datei libums4sql.so heissen !
Das war schon mal der richtige anhaltspunkt ... damit scheint der erste Fehler verschwunden zu sein ... dafür hab ich jetzt mehr dazu bekommen ;-/
was sagt einem das hier: ??
/tmp/ccqKrcHG.o: In function `main':
/tmp/ccqKrcHG.o(.text+0x6e): undefined reference to `umsLogin(bsString, bsString)'
/tmp/ccqKrcHG.o(.text+0xa9): undefined reference to `umsReadMsg(base *, bsString)'
/tmp/ccqKrcHG.o(.text+0xef): undefined reference to `umsLogout(base *)'
[ diese funktionen will ich aus der lib heraus benutzen ]
./libums4sql.so: undefined reference to `base'
./libums4sql.so: undefined reference to `umsDatabase::disconnect(BASE *)'
./libums4sql.so: undefined reference to `umsQuery::Add(bsString)'
./libums4sql.so: undefined reference to `umsDatabase::umsDatabase(void)'
./libums4sql.so: undefined reference to `umsDatabase::connected(void)'
./libums4sql.so: undefined reference to `umsQuery::Clear(void)'
./libums4sql.so: undefined reference to `BASE::getError(void)'
./libums4sql.so: undefined reference to `BASE::setError(bsString)'
./libums4sql.so: undefined reference to `umsDatabase::connect(void)'
./libums4sql.so: undefined reference to `umsQuery::FieldbyName(bsString)'
./libums4sql.so: undefined reference to `umsQuery::Open(pg_conn *)'
./libums4sql.so: undefined reference to `umsQuery::isEmpty(void)'
./libums4sql.so: undefined reference to `umsDatabase::getLastError(void)'
./libums4sql.so: undefined reference to `umsQuery::umsQuery(void)'
[und das sind Klassen, die ich in der lib intern benutze ...]
Re: lib programmieren
Hm ... schwer zu sagen was da schief gegangen ist.
Du hast schon Prototypen für alle "externen" (also nicht nur intern benutzen) Funktionen der libs erstellt, oder etwa nicht ?
Am besten eine Header-File "ums4sql.h" erstellen, und dort die ganzen Prototypen setzen, und "ums4sql.h" dann von allen Programmen die die Lib benutzen includen.
Was passiert denn, wenn du nicht gegen die Libs linkst, sondern einfach mal alle Object-Files (*.o) aus denen du die Lib erstellt hast statisch dazulinkst ?
Du hast schon Prototypen für alle "externen" (also nicht nur intern benutzen) Funktionen der libs erstellt, oder etwa nicht ?
Am besten eine Header-File "ums4sql.h" erstellen, und dort die ganzen Prototypen setzen, und "ums4sql.h" dann von allen Programmen die die Lib benutzen includen.
Was passiert denn, wenn du nicht gegen die Libs linkst, sondern einfach mal alle Object-Files (*.o) aus denen du die Lib erstellt hast statisch dazulinkst ?
Re: lib programmieren
Was auch noch plausibel wäre:
Du hast die Library doch nicht etwa mit strip aller Symbole beraubt ?!
Du hast die Library doch nicht etwa mit strip aller Symbole beraubt ?!
Re: lib programmieren
Hi!
Wichtig ist außerdem, dass die Bibliothek beim Compileraufruf _nach_ den Objektdateien angegeben wird.
Also immer "gcc -o foo foo.o -lbar" und nicht "gcc -o foo -lbar foo.o".
Cheers,
Wolfgang
Wichtig ist außerdem, dass die Bibliothek beim Compileraufruf _nach_ den Objektdateien angegeben wird.
Also immer "gcc -o foo foo.o -lbar" und nicht "gcc -o foo -lbar foo.o".
Cheers,
Wolfgang