175 votes

Bibliothèque partagée dynamique C ++ sous Linux

C'est un suivi de la Dynamique de la Bibliothèque Partagée de la compilation avec g++.

Je suis en train de créer une classe partagée de la bibliothèque en C++ sur Linux. Je suis en mesure d'obtenir à la bibliothèque de la compilation, et je peux les appeler de la (non-classe) de fonctions en utilisant les tutoriels que j'ai trouvé ici et ici. Mes problèmes commencent lorsque j'essaie d'utiliser les classes qui sont définies dans la bibliothèque. Le deuxième tutoriel que j'ai liée montre comment charger les symboles pour créer des objets, des classes définies dans la bibliothèque, mais ne s'arrête d' utiliser ces objets pour obtenir le travail fait.

Personne ne sait d'une plus tutoriel complet pour la création partagée bibliothèques de classe C++ qui montre également comment utiliser ces classes dans un exécutable séparé? Un très simple tutoriel qui montre la création de l'objet, de l'utilisation (simple getters et setters serait bien), et la suppression serait fantastique. Un lien ou une référence à un code open source qui illustre l'utilisation d'une bibliothèque de classe serait tout aussi bon.


Bien que les réponses de codelogic et nimrodm faire un travail, je voulais juste ajouter que j'ai ramassé une copie de Début de Linux Programmation depuis posant cette question, et son premier chapitre a exemple de code C et de bonnes explications pour la création et l'utilisation à la fois statiques et des bibliothèques partagées. Ces exemples sont disponibles par le biais de Google Recherche de livres dans une ancienne édition de ce livre.

164voto

codelogic Points 22722

myclass.h

#ifndef __MYCLASS_H__
#define __MYCLASS_H__

class MyClass
{
public:
  MyClass();

  /* use virtual otherwise linker will try to perform static linkage */
  virtual void DoSomething();

private:
  int x;
};

#endif

myclass.cc

#include "myclass.h"
#include <iostream>

using namespace std;

extern "C" MyClass* create_object()
{
  return new MyClass;
}

extern "C" void destroy_object( MyClass* object )
{
  delete object;
}

MyClass::MyClass()
{
  x = 20;
}

void MyClass::DoSomething()
{
  cout<<x<<endl;
}

class_user.cc

#include <dlfcn.h>
#include <iostream>
#include "myclass.h"

using namespace std;

int main(int argc, char **argv)
{
  /* on Linux, use "./myclass.so" */
  void* handle = dlopen("myclass.so", RTLD_LAZY);

  MyClass* (*create)();
  void (*destroy)(MyClass*);

  create = (MyClass* (*)())dlsym(handle, "create_object");
  destroy = (void (*)(MyClass*))dlsym(handle, "destroy_object");

  MyClass* myClass = (MyClass*)create();
  myClass->DoSomething();
  destroy( myClass );
}

Sur Mac OS X, compiler avec:

g++ -dynamiclib -flat_namespace myclass.cc -o myclass.so
g++ class_user.cc -o class_user

Sur Linux, compiler avec:

g++ -fPIC -shared myclass.cc -o myclass.so
g++ class_user.cc -ldl -o class_user

Si c'était pour un système de plugin, vous pouvez utiliser MyClass comme une classe de base et de définir toutes les fonctions nécessaires virtuel. L'auteur du plugin serait alors de dériver à partir de Maclasse, remplacer les virtuals et de mettre en oeuvre create_object et destroy_object. Votre application principale n'aurait pas besoin d'être modifié en aucune façon.

54voto

nimrodm Points 9191

La figure suivante montre un exemple d'une classe partagée la bibliothèque partagée.[h,rpc] et un main.cpp module à l'aide de la bibliothèque. C'est un exemple très simple et le makefile pourrait être beaucoup mieux. Mais il fonctionne et peut vous aider à:

partagé.h définit la classe:

class myclass {
   int myx;

  public:

    myclass() { myx=0; }
    void setx(int newx);
    int  getx();
};

shared.cpp définit la getx/setx fonctions:

#include "shared.h"

void myclass::setx(int newx) { myx = newx; }
int  myclass::getx() { return myx; }

main.cpp utilise la classe,

#include <iostream>
#include "shared.h"

using namespace std;

int main(int argc, char *argv[])
{
  myclass m;

  cout << m.getx() << endl;
  m.setx(10);
  cout << m.getx() << endl;
}

et le fichier makefile qui génère libshared.donc, et les liens principaux avec la bibliothèque partagée:

main: libshared.so main.o
    $(CXX) -o main  main.o -L. -lshared

libshared.so: shared.cpp
    $(CXX) -fPIC -c shared.cpp -o shared.o
    $(CXX) -shared  -Wl,-soname,libshared.so -o libshared.so shared.o

clean:
    $rm *.o *.so

À l'exécution réelle "principal" et le lien avec libshared.donc vous aurez probablement besoin de spécifier le chemin de chargement (ou de le mettre dans /usr/local/lib ou similaire).

Le suivant spécifie le répertoire courant comme le chemin de recherche pour les bibliothèques et les pistes principales (bash syntaxe):

export LD_LIBRARY_PATH=.
./main

De voir que le programme est lié avec libshared.ainsi, vous pouvez essayer la commande ldd:

LD_LIBRARY_PATH=. ldd main

Imprime sur ma machine:

  ~/prj/test/shared$ LD_LIBRARY_PATH=. ldd main
    linux-gate.so.1 =>  (0xb7f88000)
    libshared.so => ./libshared.so (0xb7f85000)
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb7e74000)
    libm.so.6 => /lib/libm.so.6 (0xb7e4e000)
    libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0xb7e41000)
    libc.so.6 => /lib/libc.so.6 (0xb7cfa000)
    /lib/ld-linux.so.2 (0xb7f89000)

9voto

Matt Lewis Points 399

Fondamentalement, vous devez inclure le fichier d'en-tête dans le code où vous souhaitez utiliser la classe dans la bibliothèque partagée. Puis, quand vous faites le lien, utilisez l'option '-l' indicateur de lier votre code avec la bibliothèque partagée. Bien sûr, cela nécessite l' .donc, pour être là où le système d'exploitation peut le trouver. Voir 3.5. L'installation et l'Utilisation d'une Bibliothèque Partagée

À l'aide de dlsym est pour quand on ne sait pas au moment de la compilation de la bibliothèque que vous souhaitez utiliser. Ce n'est pas, comme c'est le cas ici. Peut-être que la confusion est que Windows appelle les bibliothèques chargées dynamiquement si vous ne le reliant à la compilation ou de l'exécution (avec des analogues méthodes)? Si oui, alors vous pouvez penser de dlsym comme l'équivalent de la fonction LoadLibrary.

Si vous avez vraiment besoin de charger dynamiquement les bibliothèques (c'est à dire, ils sont des plugins), alors cette FAQ devrait aider.

2voto

Scottie T Points 4655

Chapitre 1 du Livre de recettes de C++ a plusieurs scénarios pour bâtiment statique et dynamiques bibliothèques C++ à l’aide de divers outils de construction, incluent marque, Boost.build et quelques IDEs.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X