Shared lib mit mehreren Klassen / Konstruktorargumente beim instanzieren



  • Hallo,

    ich versuche für eine applikation ein einfaches Plugin-System zu enwickeln.

    Der User soll durch ableiten von einer vordefinierten Basisklasse eine shared
    library schreiben können, die von der Applikation dann dynamisch geladen werden kann.

    Es funktioniert soweit auch schon ganz gut, solange ich pro shared lib immer nur
    eine Klasse implementiere.

    Hier mal ein Testcase:

    Die Basisklasse in der Applikation:

    #ifndef SHAPE_H_
    #define SHAPE_H_
    
    #include <map>
    #include <string>
    
    using namespace std;
    
    class Shape
    {
    public:
    	Shape();
    	virtual ~Shape();
    	virtual void draw() = 0;
    };
    
    typedef Shape *maker_t();
    
    #endif /*SHAPE_H_*/
    
    #include "Shape.h"
    
    Shape::Shape()
    {
    }
    
    Shape::~Shape()
    {
    }
    

    Zwei abgeleitete Klassen, kompiliert als shared library:

    #ifndef CIRCLE_H_
    #define CIRCLE_H_
    
    #include "Shape.h"
    #include <iostream>
    
    class Circle : public Shape
    {
    public:
    	Circle();
    	virtual ~Circle();
    	void draw();
    };
    
    #endif /*CIRCLE_H_*/
    
    #include "Circle.h"
    
    Circle::Circle()
    {
    }
    
    Circle::~Circle()
    {
    }
    
    void Circle::draw() {
    
      std::cout << "drawing circle" << std::endl;
    }
    
    extern "C" {
    
      Shape* create() {
        return new Circle;
      }
    }
    
    #ifndef SQUARE_H_
    #define SQUARE_H_
    
    #include "Shape.h"
    #include <iostream>
    
    class Square : public Shape
    {
    public:
    	Square();
    	virtual ~Square();
    	void draw();
    };
    
    #endif /*SQUARE_H_*/
    
    #include "Square.h"
    
    Square::Square()
    {
    }
    
    Square::~Square()
    {
    }
    
    void Square::draw() {
    
      std::cout << "draw square !" << std::endl;
    }
    
    extern "C" {
    	 Shape* square_create(){
    		return new Square;
    	}
    }
    

    Hier die main:

    #include <iostream>
    #include <map>
    #include <dlfcn.h>
    #include "Shape.h"
    
    int main(int argc, char **argv){
    
      void* dlib = dlopen("/path/to/libExternal.so", RTLD_NOW);
    
      maker_t* create_circle = (maker_t*) dlsym(dlib, "create_circle");
      Shape* circle = create_circle();
      circle->draw(); // korrekte ausgabe
    
      maker_t* create_square = (maker_t*) dlsym(dlib, "create_square");
      Shape* square = create_square();
      square->draw(); // segfault
    
    }
    

    Das instanzieren und ausführen des ersten objektes funktioniert einwandfrei,
    beim Aufruf von square->draw() bekomme ich jedoch ein segmentation fault.

    Wenn ich es richtig verstanden habe erkläre ich die funktionen create() und square_create() als extern "C" um auf sie als symbole mittels dlsym zugreifen zu können. Sitze nun schon seit 2 Tagen dran und kann mir das segfault beim zweiten objekt nicht erklären.

    Meine zweite Frage ist: Wie kann ich an aus einer shared lib instanzierte Klassen Argumente übergeben?

    Sorry für das lange posting, dachte aber ein testcase wäre recht nützlich.

    -robert



  • Einmal schreibst du square_create und einmal create_square (und einmal create und einmal create_circle).

    Du solltest vielleicht auch überprüfen, ob dlsym/dlopen nicht NULL zurück gibt.

    using namespace std;
    

    In Headern sollte man kein using namespace verwenden. Das macht sonst den Sinn von namespaces kaputt.



  • ups, vielen dank. da bin ich wohl zu lang vorm rechner gesessen dass ich das
    übersehen hab ...

    Den Namespace std im header reinzuholen mach ich nur in testcases um mir tipparbeit zu ersparen, in der richtigen app nehm ichs dort raus und verwende
    std::.

    Das mit den Konstruktorargumenten hab ich auch hinbekommen, einfach an die
    typedef funktion maker_t übergeben.

    vielen dank !


Log in to reply