[wrapper C++ de dlsym Cf. dlopen]

Le
hackervalley
Voila , j'essaye de faire un wrapper de dlopen.
Je bloque sur dlsym, car je n'arrive pas à avoir l'adresse du symbol.
Mon code donne ceci :

Filename :libModule1.so
Flag :2
Handle :0x804ab90
libModule1.so open
vInitModules1 0
./PluginDemo: undefined symbol: vInitModules1

Une indication serrait la bien venue.
Voici le code :

[Makefile]
all: demonstration module

# Create object file
# -fPIC flag. PIC stands for "Position Independent Code"
#Creating a Shared Library
# g++ -shared -Wl,-soname,your_soname -o library_name file_list library_list
module:
g++ -fPIC -Wall -g -c Module1.cc
g++ -shared -Wl,-soname,libModule1.so -o libModule1.so Module1.o

demonstration:
g++ -Wall -o PluginDemo Plugin.cc main.cc -ldl
# -ldl link libdl dlopen library

clean :
rm -f *.o *.so* PluginDemo

.PHONY : clean

[Module1.cc]
#include <iostream>

using namespace std;

void vInitModules1(void)
{
cout << "Module 1" << endl;
}

[Plugin.hh]
#ifndef PLUGIN_HH
#define PLUGIN_HH

extern "C"
{
// Header for dynamically load libraries
#include <dlfcn.h>
}

#include <string>

using namespace std;

class CPlugin
{
public :

CPlugin();

// See <dlfcn.h> for definition of flag
void vOpen(const string filename, int flag=RTLD_NOW);
void vClose();
void vSymbol(const char *symbol);

private:
const string filename;
int flag;
void *handle;
char *error;
const char *symbol;
void *sym;
};

[Plugin.cc]
#include "Plugin.hh"

#include <iostream>

using namespace std;

CPlugin::CPlugin ()
{
}

void
CPlugin::vOpen (const string filename, int flag)
{

handle = dlopen (filename.c_str (), flag);

cout << "Filename :" << filename << endl;
cout << "Flag :" << flag << endl;
cout << "Handle :" << handle << endl;

if (!handle)
{
error = dlerror ();
cout << error << endl;
exit(1);
}
else
cout << filename << " open " << endl;
}

void
CPlugin::vClose ()
{
if (dlclose (handle) != 0)
{
error = dlerror ();
cout << string(error) << endl;
cout << filename << " NOT CLOSED " << endl;
}
else
cout << "Shared Object closed " << endl;
}

void
CPlugin::vSymbol(const char * symbol)
{
dlerror(); /* Clear any existing error */
sym = dlsym(handle, symbol);
cout << symbol << " " << sym << endl;
if (!sym)
{error = dlerror();
if (error != 0)
cout << error << endl;
exit(1);
}
else
cout << symbol << " " << sym << endl;
}

[main.cc]
#include <iostream>
#include "Plugin.hh"

using namespace std;

int
main (int argc, char **argv)
{
CPlugin plugin;

plugin.vOpen("libModule1.so");

/*
If only filename define LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
*/

plugin.vSymbol("vInitModules1");

plugin.vClose();

return 0;
}

A++
hackervalley
http://hackervalley.free.fr
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Frédéric Lachasse
Le #718880
"hackervalley" news:408058da$0$493$
Voila , j'essaye de faire un wrapper de dlopen.
Je bloque sur dlsym, car je n'arrive pas à avoir l'adresse du symbol.
Mon code donne ceci :
[Code coupé car non-important]


Le post est un peu hors-sujet, car C++ n'a pas la notion de DLL/dydnamic
linked libraries/shared libraries/shared objects. Mais le problème est
classique et la solution fait partie du langage C++.

Le problème: la décoration de nom ou "name mangling". C++ permet
d'"overloader" les fonctions, c'est-à-dire permet d'avoir des fonctions
ayant le même nom à condition que leurs signatures (types et nombres
d'arguments) soient différentes. Par exemple:

int mod(int a, int b); // modulo de 2 entiers
int mod(double a, double b); // modulo de 2 réels

Cela veut dire que dans une DLL, les deux fonctions doivent avoir des nom
différents. Pour cela, le compilateur C++ "décore" (mangle) le nom de la
fonction en ajoutant un codage en fonction des arguments (et parfois du type
de retour). Par exemple:

mod__II_I (fonction mod avec 2 int retournant un int)
mod__DD_I (function mod avec 2 double retournant un int)

Cette décoration est totalement dépendante du compilateur (cela explique que
les compilateurs C++ sont rarement compatible entre eux). Pour trouver le
symbole dans une DLL, il faut utiliser le nom décoré. Ce qui est plutôt
pénible, le système de décoration étant souvant compliqué et rarement
documenté.

Par contre, il y a un moyen de dire au compilateur de ne pas décorer une
fonction. Cela permet au compilateur C++ d'appeler des fonctions générées
par un compilateur C (qui ne sont pas décorées) ou de faire des fonctions
appelables par un programme C (qui ne sait pas décorer). Ce moyen est la
déclaration extern "C".

// Déclaration d'une fonction dont le nom ne sera pas décoré:
extern "C" void vInitModules1(void);

// Si on définit la fonction plus loin, il n'est pas nécessaire
// de répéter extern "C"
void vInitModules1()
{
//...
}

Ainsi, il sera beaucoup plus facile de trouver la fonction avec dlsym dans
la DLL.

--
Frédéric Lachasse - ECP86

Jean-Marc Bourguet
Le #718606
"Frédéric Lachasse"
Cette décoration est totalement dépendante du compilateur (cela explique que
les compilateurs C++ sont rarement compatible entre eux).


Voir la FAQ, question 7.1 et 7.2, ta description renverse un peu la
dépendance (la situation est plutôt que les compilateurs sont rarement
compatibles et qu'on s'assure que le problème est détecté aussi
rapidement que possible en utilisant des décorations différentes).

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

hackervalley
Le #718605
Merci pour ces indications, le code "marche".

A++
Publicité
Poster une réponse
Anonyme