C++ dlopen mini-HOGYAN

Aaron Isotton

2003.08.12

Verzi�t�rt�net
Verzi�: 1.032003.08.12�tdolgozta: AI
Referencia hozz�ad�sa a GLib dinamikus modul bet�lt�j�r�l. K�sz�net �rte G. V. Sriraam-nak.
Verzi�: 1.022002.12.08�tdolgozta: AI
GYIK hozz�ad�sa. Kisebb v�ltoztat�sok.
Verzi�: 1.012002.06.30�tdolgozta: AI
Friss�tett magyar�zat a virtu�lis dekonstuktorokr�l. Kisebb v�ltoztat�sok.
Verzi�: 1.002002.06.19�tdolgozta: AI
A „Szerz�i jog �s licenc” fejezet az elej�re ker�lt. „A dokumentumban haszn�lt kifejez�sek” fejezet hozz�ad�sa. Kisebb v�ltoztat�sok.
Verzi�: 0.972002.06.19�tdolgozta: JYG
Egy kis sz�t�r, valamint mondat-szint� v�ltoztat�sok.
Verzi�: 0.962002.06.12�tdolgozta: AI
Irodalomjegyz�k hozz�ad�sa. Az extern f�ggv�nyek �s v�ltoz�k le�r�s�nak jav�t�sa.
Verzi�: 0.952002.06.11�tdolgozta: AI
Kisebb jav�t�sok.

Tartalomjegyz�k
1. Bevezet�
1.1. Szerz�i jog �s licenc
1.2. A felel�ss�g teljes elh�r�t�sa
1.3. K�zrem�k�d�k
1.4. Visszajelz�s
1.5. A dokumentumban haszn�lt kifejez�sek
1.6. Magyar ford�t�s
2. A probl�ma
2.1. „N�v sz�tszed�se”
2.2. Oszt�lyok
3. A megold�s
3.1. extern "C"
3.2. F�ggv�nyek bet�lt�se
3.3. Oszt�lyok bet�lt�se
4. Gyakran Ism�telt K�rd�sek
5. Tov�bbi inform�ci�
Irodalomjegyz�k

1. Bevezet�

UNIX C++ programoz�kban felmer�l� gyakori k�rd�s, hogyan t�ltsenek be dinamikusan C++ f�ggv�nyeket �s oszt�lyokat a dlopen haszn�lat�val.

T�ny, hogy nem minden esetben egyszer� ez, �s n�mi magyar�zatot ig�nyel. Ez van le�rva ebben a mini-HOGYANban.

Egy �tlagos C �s C++ programoz�si nyelv ismeret valamint a dlopen API ismerete sz�ks�ges ahhoz, hogy meg�rthesd ezt a dokumentumot.

Ez a HOGYAN els�dleges a http://www.isotton.com/howtos/C++-dlopen-mini-HOWTO/ webhelyen tal�lhat� meg.


1.3. K�zrem�k�d�k

�r�mmel mondok k�sz�netet az al�bbi szem�lyeknek (abc sorrendben):


1.6. Magyar ford�t�s

A magyar ford�t�st Szalai Ferenc k�sz�tette (2004.04.17). A lektor�l�st Daczi L�szl� v�gezte el (2004.05.04). Utolj�ra jav�tva 2004.05.05.-�n (r2). A dokumentum legfrissebb v�ltozata megtal�lhat� a Magyar Linux Dokument�ci�s Projekt honlapj�n.


2. A probl�ma

N�ha fut�sid�ben kellene bet�lteni programk�nyvt�rakat (�s haszn�lni a f�ggv�nyeiket). Ez legink�bb akkor sz�ks�ges, ha valamilyen plug-in vagy modul architekt�r�j� programot �rsz.

A C nyelvben a program k�nyvt�rak bet�lt�se igen egyszer� (dlopen, dlsym �s dlclose megh�v�sa elegend�). C++-al ez egy kicsit bonyolultabb. A C++ program k�nyvt�rak bet�lt�s�nek neh�zs�get r�szint a „nevek sz�tszed�se”, r�szben pedig az a t�ny okozza, hogy a dlopen API C-ben lett �rva, �gy nem teszi lehet�v� oszt�lyok egyszer� bet�lt�s�t.

Miel�tt bemutatn�nk a programk�nyvt�rak bet�lt�s�t, C++-ban megvizsg�ljuk a „n�v sz�tszed�si” probl�m�t egy kicsit alaposabban. Azt aj�nlom akkor is olvasd el ezt a r�szt, ha nem �rdekel, mert seg�t meg�rteni mi is a probl�ma �s mi a megold�sa.


2.1. „N�v sz�tszed�se”

Minden C++ programban (vagy programk�nyvt�rban vagy t�rgyk�d �llom�nyban) minden nem statikus f�ggv�ny a bin�ris �llom�nyban szimb�lumokkal van reprezent�lva. Ezek a szimb�lumok speci�lis karaktersorozatok, amik egy�rtelm�en azonos�tj�k a f�ggv�nyt a programban, programk�nyvt�rban vagy t�rgyk�d �llom�nyban.

C-ben a szimb�lum nevek megegyeznek a f�ggv�nyek neveivel: az strcpy f�ggv�ny szimb�luma strcpy �s �gy tov�bb. Ez az�rt lehets�ges, mert C-ben k�t nem statikus f�ggv�nynek nem lehet azonos a neve.

Mivel a C++ enged�lyezi az �tdefini�l�st (overloading - k�l�nb�z� f�ggv�nyek azonos n�vvel, de k�l�nb�z� argumentumokkal), valamint sz�mos �j tulajdons�ga van, ami a C-nek nincs — mint oszt�lyok, tagf�ggv�nyek, kiv�tel kezel�s — ez�rt nem lehets�ges a f�ggv�nyek nev�t egyszer�en szimb�lumn�vnek haszn�lni. A C++ ezt az probl�m�t az �gynevezett „n�v sz�tszed�ssel” (mangling) oldja meg. Ez �gy m�k�dik, hogy a a f�ggv�nyek �s egy�b sz�ks�ges inform�ci�k (mint az argumentumok sz�ma �s m�rete) alapj�n l�trehoz egy csak a ford�t� sz�m�ra �rtelmes karaktersorozatot, amit az szimb�lum n�vnek tud haszn�lni. A foo f�ggv�ny ilyen m�don el��ll�tott neve �gy n�zhet ki p�ld�ul: foo@4%6^. Vagy nem is felt�tlen kell tartalmaznia a "foo" sz�t mag�t.

Az egyik probl�ma ezzel az elj�r�ssal az, hogy a C++ standard (jelenleg [ISO14882]) nem defini�lja ennek a menet�t. �gy minden ford�t� a saj�t m�dszer�t haszn�lja. N�h�ny ford�t� meg is v�ltoztatja az algoritmust verzi�r�l verzi�ra (k�l�n�sen a g++ 2.x �s 3.x k�z�tt). Ez�rt ha ki is tal�ltad, hogy a te ford�t�d hogyan is m�k�dik e tekintetben (�s �gy be fogod tudni t�lteni a f�ggv�nyeidet a dlsym seg�ts�g�vel) ez val�sz�n�leg csak a te ford�t�ddal fog m�k�dni �s haszn�lhatatlan lesz annak k�vetkez� verzi�j�val.


3. A megold�s


3.2. F�ggv�nyek bet�lt�se

C++ a f�ggv�nyek �gy t�lthet�ek be mint C-ben; a dlsym seg�ts�g�vel. A bet�lteni k�v�nt f�ggv�nyeket extern "C"-vel kell jel�ln�d, hogy a C-szer� szimb�lum n�vk�pz�st kik�nyszer�tsd.

A hello f�ggv�ny a hello.cpp �llom�nyban van defini�lva, mint extern "C". A main.cpp-ben t�lt�dik be a dlsym h�v�ssal. A f�ggv�nyt extern "C"-vel kell megjel�lni, mert k�l�nben nem tudjuk biztosan a hozz� tartoz� szimb�lumnevet.


3.3. Oszt�lyok bet�lt�se

Az oszt�lyok bet�lt�se egy kicsit komplik�ltabb, mert nek�nk az oszt�ly egy p�ld�ny�ra van sz�ks�g�nk, nem csak egy f�ggv�nyre mutat� mutat�ra.

Nem tudjuk l�trehozni az oszt�ly egy p�ld�ny�t a new oper�tor seg�ts�g�vel, mert az oszt�ly nincs defini�lva a futtathat� �llom�nyban, �s mert nem tudjuk a nev�t.

A megold�s a polimorfizmus seg�ts�g�vel ad�dik. Egy alap interf�sz oszt�lyt defini�lunk a futtathat� �llom�nyban virtu�lis tagf�ggv�nyekkel, �s egy sz�rmaztatott implement�ci�s oszt�lyt a modulban. �ltal�ban az interf�sz absztrakt oszt�ly (egy oszt�ly absztrakt, ha minden f�ggv�nye virtu�lis).

A dinamikus oszt�lybet�lt�st �ltal�ban plug-in-okban haszn�lj�k — Ezeknek egy vil�gosan defini�lt interf�szt kell haszn�lniuk — Egy interf�szt �s az azt implement�l� oszt�lyokat kell defini�lnunk.

Ezek ut�n - m�g mindig a modulban - defini�lunk k�t tov�bbi seg�df�ggv�nyt (�gynevezett class factory functions). Az egyik f�ggv�ny ezek k�z�l elk�sz�ti egy p�ld�ny�t az oszt�lynak, �s egy arra ir�ny�tott mutat�t ad vissza. M�g a m�sik egy oszt�lyra ir�ny�tott mutat�t kap (amit a factory k�sz�tett) �s felszabad�tja azt. Ezt a k�t f�ggv�nyt extern "C" direkt�v�val jel�lj�k meg.

Ahhoz, hogy oszt�lyt t�lts be modulb�l csak a k�t factory f�ggv�nyt kell bet�ltened a dlsym seg�ts�g�vel. Szerkeszteni (link) ugyan�gy kell, mint ahogy azt ebben r�szben tett�k a hello f�ggv�nnyel. Ezek ut�n m�r annyi p�ld�nyt tudsz l�trehozni �s felszabad�tani az oszt�lyb�l, amennyit csak akarsz.

P�lda 2. Egy oszt�ly bet�lt�se

Itt mi most egy �ltal�nos polygon oszt�lyt haszn�lunk, mint interf�sz �s egy sz�rmaztatott triangle oszt�lyt, mint implement�ci�t.

main.cpp:

#include "polygon.hpp"
#include <iostream>
#include <dlfcn.h>

int main() {
    using std::cout;
    using std::cerr;

    // load the triangle library
    void* triangle = dlopen("./triangle.so", RTLD_LAZY);
    if (!triangle) {
        cerr << "Cannot load library: " << dlerror() << '\n';
        return 1;
    }

    // load the symbols
    create_t* create_triangle = (create_t*) dlsym(triangle, "create");
    destroy_t* destroy_triangle = (destroy_t*) dlsym(triangle, "destroy");
    if (!create_triangle || !destroy_triangle) {
        cerr << "Cannot load symbols: " << dlerror() << '\n';
        return 1;
    }

    // create an instance of the class
    polygon* poly = create_triangle();

    // use the class
    poly->set_side_length(7);
        cout << "The area is: " << poly->area() << '\n';

    // destroy the class
    destroy_triangle(poly);

    // unload the triangle library
    dlclose(triangle);
}

polygon.hpp:

#ifndef POLYGON_HPP
#define POLYGON_HPP

class polygon {
protected:
    double side_length_;

public:
    polygon()
        : side_length_(0) {}

    void set_side_length(double side_length) {
        side_length_ = side_length;
    }

    virtual double area() const = 0;
};

// the types of the class factories
typedef polygon* create_t();
typedef void destroy_t(polygon*);

#endif

triangle.cpp:

#include "polygon.hpp"
#include <cmath>

class triangle : public polygon {
public:
    virtual double area() const {
        return side_length_ * side_length_ * sqrt(3) / 2;
    }
};


// the class factories

extern "C" polygon* create() {
    return new triangle;
}

extern "C" void destroy(polygon* p) {
    delete p;
}

N�h�ny dolgot meg kell jegyezn�nk az oszt�lyok bet�lt�s�vel kapcsolatban:


4. Gyakran Ism�telt K�rd�sek

4.1. Windowst haszn�lok �s nem tal�lom a dlfcn.h header �llom�nyt a PC-men! Mi a probl�ma?
4.2. L�tezik b�rmilyen dlopen-kompatibilis illeszt�fel�let a Windows LoadLibrary API-j�hoz?

5. Tov�bbi inform�ci�


Irodalomjegyz�k

ISO14482 ISO/IEC 14482-1998 — The C++ Programming Language. PDF �s nyomtatott k�nyv form�j�ban is el�rhet� a http://webstore.ansi.org/ webhelyen.

STR2000 Bjarne Stroustrup The C++ Programming Language, Special Edition. ISBN 0-201-70073-5. Addison-Wesley.