Boost.Extension Tutorial 1 - Problem



  • Hi,

    Ich bin ein totaler Anfänger, was die Boost-Bibliotheken betrifft und wollte jetzt Boost.Extension verwenden, um ein Plugin-basiertes Programm zu schreiben.
    Nachdem ich mich durch die Installation der Boost-Bibliotheken gekämpft hatte, wollte ich Tutorial 1 zu Extension ausprobieren:
    [url]http://boost-extension.redshoelace.c...als.tutorial01 [/url]

    Also habe ich die folgenden Dateien & Ordner angelegt:
    shared_test/
    ..|
    ..+- Jamroot
    ..+- tutorial_1/
    .........|
    .........+- hello_world.cpp
    .........+- main.cpp

    Jamroot sieht so aus:

    import type : change-generated-target-suffix ;
    import type : change-generated-target-prefix ;
    type.change-generated-target-suffix SHARED_LIB : : extension ;
    type.change-generated-target-prefix SHARED_LIB : : lib ; 
    
    import os ;
    
    local BOOST_ROOT = [ os.environ /usr/local/include/boost ] ; 
    project
        : requirements
          <include>#(BOOST_ROOT)
        :
        ;
    
    lib tutorial_1 : tutorial_1/hello_world.cpp : <link>shared ;
    exe tutorial_1_bin : tutorial_1/main.cpp ;
    
    install binaries :
      tutorial_1 tutorial_1_bin
      ;
    

    hello_world.cpp sieht so aus:

    #include <iostream>
    #include <boost/extension/extension.hpp>
    
    extern "C"
    
    void BOOST_EXTENSION_EXPORT_DECL
    boost_extension_hello_world (int repetitions)
    {
        for (int i = 0; i < repetitions; i++) {
            std::cout << "Hello, World!" << std::endl;
        }
    }
    

    Und main.cpp sieht so aus:

    #include <iostream>
    #include <boost/extension/shared_library.hpp>
    #include <boost/function.hpp>
    
    class shared_library;
    
    int main()
    {
        std::string library_path = "libtutorial_1.extension";
        shared_library lib(library_path);
        if (!lib.open()) {
            std::cerr << "Library failed to open: " << library_path << std << endl;
            return 1;
        }
    
        boost::function<void (int)>
          f(lib.get<void, int>("boost_extension_hello_world"));
    
        if (!f) {
            std::cerr << "Function not found!" << std::endl;
            return 1;
        }
    
        f(4);
    }
    

    ⚠ Jetzt zum Problem: Wenn ich mich im "shared_test"-Ordner befinde und die Dateien mittels
    bjam
    zu kompilieren versuche, erhalte ich die folgenden Fehlermeldungen:

    gcc.compile.c++ bin/gcc-4.4.3/debug/tutorial_1/main.o 
    tutorial_1/main.cpp: In function ‘int main()’: 
    tutorial_1/main.cpp:10: error: variable ‘shared_library lib’ has initializer but incomplete type 
    tutorial_1/main.cpp:12: error: expected primary-expression before ‘<<’ token 
    tutorial_1/main.cpp:12: error: ‘endl’ was not declared in this scope 
    tutorial_1/main.cpp:17: error: expected primary-expression before ‘void’ 
    tutorial_1/main.cpp:17: error: expected primary-expression before ‘int’
    

    Sieht hier irgendjemand das Problem? Ich bin mir sicher, dass es ein Anfängerfehler ist. 🙄



  • Die erste Fehlermeldung sagt aus, dass Du ein Objekt vom Typ shared_library erstellen möchtest, obwohl shared_library unvollständig ist. Das ist auch klar, da Du sie nur forward deklarierst (über main).

    Du meintest vermutlich die in boost/extension/shared_library.hpp mit Sicherheit vollständig definierte Klasse boost::extensions::shared_library?



  • Genau diese meinte ich :). Weißt du denn, was ich am Code ändern muss, damit es funktioniert?



  • Also den Fehler für die genannten Fehlermeldungen habe ich mittels Entfernung der Vorwärtsdeklaration und Benutzung des passenden Namespaces gelöst (vielen Dank für die Hilfe!), sodass main.cpp jetzt so aussieht:

    [code]#include <iostream>
    #include <boost/extension/shared_library.hpp>
    #include <boost/function.hpp>
    [b]using namespace boost::extensions;[/b]
    
    int main()
    {
        std::string library_path = "libtutorial_1.extension";
        shared_library::shared_library lib(library_path);
        //...
        // "std << endl" war ebenfalls fehlerhaft
            std::cerr << "Library failed to open: " << library_path << [b]std::endl[/b];
        //...
    }[/code]
    

    Jetzt kommen aber viel kryptischere Fehlermeldungen:
    gcc.compile.c++ bin/gcc-4.4.3/debug/tutorial_1/main.o
    gcc.link bin/gcc-4.4.3/debug/tutorial_1_bin
    bin/gcc-4.4.3/debug/tutorial_1/main.o: In function boost::extensions::impl::load\_shared_library(char const*)': /usr/local/include/boost/extension/impl/library_impl.hpp:60: undefined reference todlopen'
    bin/gcc-4.4.3/debug/tutorial_1/main.o: In function boost::extensions::impl::get\_function(void*, char const*)': /usr/local/include/boost/extension/impl/library_impl.hpp:64: undefined reference todlsym'
    bin/gcc-4.4.3/debug/tutorial_1/main.o: In function boost::extensions::impl::close\_shared_library(void*)': /usr/local/include/boost/extension/impl/library_impl.hpp:67: undefined reference todlclose'

    Könnte der Grund hierfür in einem fehlerhaften Jamfile liegen?



  • Das sind jetzt Linkerfehler. Boost.Extension findet die Funktionen zum Öffnen von shared libraries nicht. Abhilfe würde hier -ldl beim Linken bringen.

    Wie (und ob) man das ganze beim Linken der Boost.Extension-Bibliothek (Jamfile) selbst lösen kann, wüsste ich jetzt nicht.



  • Ah, verstehe, dann werden also die dl-Bibliotheken nicht richtig gelinkt. Dann bleibt nur noch die Frage, wie ich das mit meiner bisherigen Methode behoben bekomme. Ich werde es mal ohne Jamfile ausprobieren und schauen, was passiert. Längerfristig werde ich aber wohl wieder auf Bjam zurückgreifen, um das Projekt einfach organisieren zu können.



  • So, ich habe jetzt mal alles per Hand kompilieren lassen. Und zwar mit Hilfe folgender Befehle.

    Für die dynamische Bibliothek hello_world.cpp:

    sudo g++ -shared -fPIC hello_world.cpp -o libhello.so
    

    Dann das eigentliche Programm:

    sudo g++ -o hello main.cpp -ldl
    

    Wenn ich das nun ausführe, wird leider nicht die dynamische Bibliothek geladen. Wie ich es in main.cpp gefordert habe, wird dies signalisiert:

    Library failed to open: libhello.so
    

    Kann der Fehler nun noch an einer der beiden Quelldateien liegen, wenn das Kompilieren selber funktioniert hat? Oder kann es durch fehlerhafte Compilerparameter verursacht sein?


Anmelden zum Antworten