Statischen Konstruktor in Libraries aufrufen.
-
Hallo
erstmal, ich weiß nicht ob hier das richtige Forum ist, aber könnt ja verschieben, wenns nicht hierher passt.
Mein Problem ist folgendes:
Ich habe eine Klasse in einer Static-Library, von der ein statisches Objekt erstellt wird. Wenn ich die Library einbinde, wird aber der Konstruktor des Objekts nicht aufgerufen. Andersgesagt das Objekt wird nicht erstellt.Der Code dazu:
bib.cpp ist der Source der Statischen-Library#include <iostream> struct A { A(){ std::cout << "A::A()" << std::endl; } }; A a; // Wird nicht aufgerufen!!!
die cpp des Programms:
#include <iostream> int main() { std::cout << "main()\n"; return 0; }
Also es wird einfach nur main() ausgegeben.
Kompilieren tue ich bzw. scons auf folgende weise:
g++ -c -o bib.o bib.cpp ar r libbib.a bib.o ranlib libbib.a g++ -c -o prog.o prog.cpp g++ -o prog prog.o -L. -lbib
Weiß jemand woran das liegt und wie man das doch noch richtig hinbiegen kann?
-
ich denk das extern keyword sollt da abhilfe schaffen.
-
Ne, hat nichts gebracht.
-
hmmh... lag wohl falsch
ich schau später wie's geht
-
hi,
dumme Frage: woher soll denn der Linker wissen, dass in deinem main A benutzt werden soll?
vgv tesu
-
Irgendwo die Adresse von a zu nehmen sollte den Linker zwingen den entsprechenden Code mit zu linken. Laufzeitmässig dürftest du davon nix spüren, da ein einfaches "&a;" keinen Code erzeugen sollte, zumindest nicht im Release.
Normalerweise müsste es aber auch reichen wenn du irgendeine Funktion der Library aufrufst - der Linker müsste dann eigentlich den Code für die Initialisierung sämtlicher globalen Instanzen mit reinnehmen und dafür sorgen dass der vor "main()" ausgeführt wird.
-
tesuji schrieb:
hi,
dumme Frage: woher soll denn der Linker wissen, dass in deinem main A benutzt werden soll?
vgv tesudumme Gegenfrage: Wie kommst du darauf, dass in meinem main A benutzt werden soll?
Anders gesagt: Wenn ich das nicht als Library linke, sondern direkt als ne cpp-Datei dann wird der Konstruktor aufgerufen.hustbaer schrieb:
Irgendwo die Adresse von a zu nehmen sollte den Linker zwingen den entsprechenden Code mit zu linken. Laufzeitmässig dürftest du davon nix spüren, da ein einfaches "&a;" keinen Code erzeugen sollte, zumindest nicht im Release.
Hm, probiere morgen aus. Bin heute zu müde dafür.
Aber eigentlich ist es keine ideale Lösung, denn die Klassen fungieren als eine Art Plugins. Sodass das gesammte Programm bzw. der Lib-Nutzer nichts davon wissen sollten wie die konkreten Klassen aussehen.
In dem Kontruktor registrieren sich dann die Klassen als Plugins.
-
wie kann man eine cpp linken?
meinst du mit übersetzen? Falls ja, dann ist es richtig, dass der Konstruktor aufgerufen wird, denn jetzt ists ja "dabei", aber als statisch zugelinkte lib weis dein Programm nichts von A.
-
tesuji schrieb:
wie kann man eine cpp linken?
meinst du mit übersetzen?Ja, war so gemeint.
Falls ja, dann ist es richtig, dass der Konstruktor aufgerufen wird, denn jetzt ists ja "dabei", aber als statisch zugelinkte lib weis dein Programm nichts von A.
Kanns sein dass ich dich da falsch verstanden habe. Aber aus der Quelltext-Sicht weiß das Programm in beiden Fällen nichts von der Klasse. Linkt der gcc eigentlich nicht alles mit rein in das Programm?
-
Der gcc linker durchsucht die statische Lib (über den mit ar erstellten Index) und linkt nur diese Objekte zu deinem Programm, für die er Referenzen in deinen Objektmodulen gefunden hat.
vg. tesu
-
Du kannst auch deinen Plugins eine dummy Methode verpassen, und in die Library eine Funktion einbauen die für sämtliche Plugins diese dummy Methode aufruft. Ca. so:
namespace Foo { class Plugin { // ... public: void Dummy(); }; // ... APlugin a; BPlugin b; CPlugin c; void Initialize() { a.Dummy(); b.Dummy(); c.Dummy(); } } // namespace Foo
Dann muss der Client/User der Plugin Library bloss noch Foo::Initialize() irgendwo aufrufen. Wie die Plugins intern heissen, welche und wie viele es gibt ist dann egal und bleibt "versteckt".