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.

2.2. Osztályok

A másik probléma a dlopen API-val, az, hogy csak függvények betöltését támogatja. Általában azonban egy C++ programkönyvtárban egy osztályt publikálsz, amit a programodban használni szeretnél. Ezen osztály használatához egy példányt kell belőle készítened, de ez nem is olyan könnyű.