<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
     "http://docbook.org/xml/4.2/docbookx.dtd">
<article lang="hu">
  
  <articleinfo>
    
    <title>C++ dlopen mini-HOGYAN</title>
    
    <author>
      <firstname>Aaron</firstname>
      <surname>Isotton</surname>
      <affiliation>
        <address><email>aaron@isotton.com</email></address>
      </affiliation>
    </author>
    
    <pubdate>2003.08.12</pubdate>

    <revhistory>

      <revision>
	<revnumber>1.03</revnumber>
	<date>2003.08.12</date>
	<authorinitials>AI</authorinitials>
	<revremark>Referencia hozzáadása a GLib dinamikus modul betöltőjéről.
	Köszönet érte G. V. Sriraam-nak.
	  </revremark>
      </revision>
      
      <revision>
        <revnumber>1.02</revnumber>
        <date>2002.12.08</date>
        <authorinitials>AI</authorinitials>
        <revremark>GYIK hozzáadása. Kisebb változtatások.</revremark>
      </revision>

      <revision>
        <revnumber>1.01</revnumber>
	<date>2002.06.30</date>
        <authorinitials>AI</authorinitials>
        <revremark>Frissített magyarázat a virtuális dekonstuktorokról. 
		   Kisebb változtatások.</revremark>
      </revision>

      <revision>
	<revnumber>1.00</revnumber>
	<date>2002.06.19</date>
	<authorinitials>AI</authorinitials>
	<revremark>A &#8222;Szerzői jog és licenc&#8221; fejezet az elejére 
	került. &#8222;A dokumentumban használt kifejezések&#8221; fejezet hozzáadása. Kisebb változtatások.
	</revremark>
      </revision>
      
      <revision>
	<revnumber>0.97</revnumber>
	<date>2002.06.19</date>
	<authorinitials>JYG</authorinitials>
	<revremark>Egy kis szótár, valamint mondat-szintű változtatások.</revremark>
      </revision>

      <revision>
        <revnumber>0.96</revnumber>
        <date>2002.06.12</date>
        <authorinitials>AI</authorinitials>
        <revremark>Irodalomjegyzék hozzáadása. Az extern
	függvények és változók leírásának javítása.
          </revremark>
      </revision>

      <revision>
        <revnumber>0.95</revnumber>
        <date>2002.06.11</date>
        <authorinitials>AI</authorinitials>
        <revremark>Kisebb javítások.</revremark>
      </revision>

    </revhistory>
    
    <abstract>
      <para>C++ függvények és osztályok betöltése 
      a <function>dlopen</function> API segítségével.</para>
    </abstract>
    
  </articleinfo>
  
  
  <section id="intro">
    <title>Bevezető</title>
    
    <para>
      UNIX C++ programozókban felmerülő gyakori kérdés, 
      hogyan töltsenek be dinamikusan C++ függvényeket és osztályokat
       a <function>dlopen</function> használatával.
    </para>
    
    <para>Tény, hogy nem minden esetben egyszerű ez, és némi 
      magyarázatot igényel. Ez van leírva ebben a mini-HOGYANban.
      </para>
    
    <para>Egy átlagos <systemitem>C</systemitem>
      és <systemitem>C++</systemitem> programozási nyelv ismeret
      valamint a 
     <function>dlopen</function> API ismerete szükséges ahhoz, hogy 
     megérthesd ezt a dokumentumot.</para>

    <para>Ez a HOGYAN elsődleges a <ulink
        url="http://www.isotton.com/howtos/C++-dlopen-mini-HOWTO/"/> webhelyen található meg.</para>
    
    <section id="copyright">
      <title>Szerzői jog és licenc</title>

      <para>
        This document, <emphasis>C++ dlopen mini HOWTO</emphasis>, is
        copyrighted (c) 2002 by <emphasis>Aaron Isotton</emphasis>.
        A dokumentum a Free Software Foundation által kiadott GNU Free
	Documentation License 1.1-es vagy újabb verziójában foglalt
	feltételek keretein belül másolható, terjeszthető és/vagy
	módosítható; invariáns fejezet, első és hátsó
	borítólapszöveg nincsen.
	</para>    
    </section>
  
    <section id="disclaimer">
      <title>A felelősség teljes elhárítása</title>
      
      <para>
         A dokumentum tartalmáért nincs felelősségvállalás. Az
	 elgondolásokat, példákat és információkat a saját
	 felelősségedre használd. Előfordulhatnak hibák és
	 pontatlanságok, amelyek a rendszered sérülését okozhatják.
	 Minden óvatosság ellenére bármily hihetetlen, a szerző(k)
	 semmilyen felelősséget nem vállal(nak).
      </para>
      
      <para>
         Minden szerzői jog fenntartva az eredeti tulajdonosának,
	 amennyiben másként nincs jelölve. A dokumentumban használt
	 szakkifejezések semmilyen párhuzamot nem képviselnek
	 védjegyekre, szervíz márkákra vonatkozólag. Egyedi alkotások
	 vagy védjegyek nevesítése nem hozzájárulások.
      </para>
    </section>
    
    <section id="credits">
      <title>Közreműködők</title>
      
      <para>
        Örömmel mondok köszönetet az alábbi személyeknek
	(abc sorrendben):
      </para>
      
      <itemizedlist>

        <listitem>
          <para>Joy Y Goodreau <email>joyg (at) us.ibm.com</email> 
	  a szerkesztésért.</para>
        </listitem>

        <listitem>
          <para>D. Stimitis <email>stimitis (at) idcomm.com</email>
            rámutatott néhány kérdésre a formázással és a
	    név szétszedéssel kapcsolatban valamit az 
	    <literal>extern "C"</literal>-vel kapcsolatban.
            </para>
        </listitem>

      </itemizedlist>
      
    </section>
    
    <section id="feedback">
      <title>Visszajelzés</title>
      
      <para>
	Visszajelzést szívesen fogadok.
	A megjegyzéseidet, kritikádat és a hozzájárulásaidat
	a <email>aaron@isotton.com</email> címre küldheted.
      </para>
    </section>

    <section>
      <title>A dokumentumban használt kifejezések</title>

      <variablelist>
        <varlistentry>
          <term><function>dlopen</function> API</term>
          <listitem>
            <para>A <function>dlclose</function>,
              <function>dlerror</function>,
              <function>dlopen</function> és
              <function>dlsym</function> függvények, amik leírása a
              <literal>dlopen(3)</literal> kézikönyv oldalon található.</para>
            
            <para>Megjegyezzük, hogy mi a 
              <quote><function>dlopen</function></quote> kifejezést a
              <function>dlopen</function> <emphasis>függvényre</emphasis> 
	      magára, és
	      a <quote><function>dlopen</function> API</quote> kifejezést az
              <emphasis>egész API</emphasis>-ra használjuk.</para>
          </listitem>
        </varlistentry>
      </variablelist>

    </section>
    
    <section>
    <title>Magyar fordítás</title>
    <para>
    A magyar fordítást <ulink url="mailto: szferi[kukac]einstein.ki.iif[pont]hu">Szalai Ferenc</ulink> készítette (2004.04.17).
    A lektorálást <ulink url="mailto:dacas@freemail.hu_NO_SPAM">Daczi László</ulink> végezte el (2004.05.04). Utoljára javítva 2004.05.05.-én (r2).
    A dokumentum legfrissebb változata megtalálható a <ulink url="http://tldp.fsf.hu/index.html">Magyar Linux Dokumentációs Projekt</ulink> honlapján.
    </para>
  </section>
    
    <!-- Translations - ->
    <section id="translations">
    <title>Translations</title>

    <para>
    Pointers to available translations are nice.
    Also your translators tend to give very important inputs.
  </para>

    <itemizedlist>
    <listitem>
    <para>
    <ulink url="http://tldp.org/">French Translation</ulink>
    provided by Individual <email>someone (at) somewhere.fr</email>
  </para>
  </listitem>
    <listitem>
    <para>
    <ulink url="http://tlpd.org/">German Translation</ulink>
    provided by Individual <email>someone (at) somewhere.de</email>
  </para>
  </listitem>
  </itemizedlist>
  </section>
    -->
  </section>

  <section id="theproblem">
    <title>A probléma</title>

    <para>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.
      </para>

    <para>A C nyelvben a program könyvtárak betöltése igen egyszerű 
       (<function>dlopen</function>, <function>dlsym</function> és
      <function>dlclose</function> 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
      <link linkend="mangling">&#8222;nevek szétszedése&#8221;</link>,
      részben pedig az a tény okozza, hogy a <function>dlopen</function> 
      API C-ben lett írva, így nem teszi lehetővé osztályok egyszerű 
      betöltését.</para>

    <para>Mielőtt bemutatnánk a programkönyvtárak betöltését,
    C++-ban megvizsgáljuk a &#8222;név szétszedési&#8221; 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.</para>

    <section id="mangling">
      <title>&#8222;Név szétszedése&#8221;</title>

      <para>Minden C++ programban (vagy programkönyvtárban vagy
      tárgykód állományban) minden nem statikus függvény
      a bináris állományban <emphasis>szimbólumokkal</emphasis> 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.</para>

      <para>C-ben a szimbólum nevek megegyeznek a függvények
      neveivel: az <function>strcpy</function> függvény szimbóluma
      <computeroutput>strcpy</computeroutput> és így tovább.
      Ez azért lehetséges, mert C-ben két nem statikus függvénynek
      nem lehet azonos a neve.</para>

      <para>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 &mdash; 
      mint osztályok, tagfüggvények, kivétel kezelés &mdash; 
      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 
      <emphasis>&#8222;név szétszedéssel&#8221;</emphasis> (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 <function>foo</function> 
      függvény ilyen módon előállított neve így nézhet ki például:
      <computeroutput>foo@4%6^</computeroutput>.  Vagy nem is
      feltétlen kell tartalmaznia a <quote>foo</quote> szót magát.</para>

      <para> Az egyik probléma ezzel az eljárással az, hogy a
      C++ standard (jelenleg <citation>ISO14882</citation>)
      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 <function>dlsym</function> 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.</para>

    </section>

    <section>
      <title>Osztályok</title>

      <para>A másik probléma a <function>dlopen</function> API-val,
      az, hogy csak <emphasis>függvények</emphasis> 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ű.
      </para>

    </section>

  </section>

  <section id="thesolution">
    <title>A megoldás</title>

    <section id="externC">
      <title><literal>extern "C"</literal></title>
      
      <para>
      	A C++-nak van egy speciális kulcsszava arra, hogy
	függvényeket C kötéssel definiáljuk. Ez az <literal>extern "C"</literal>. 
	Az a függvény ami <literal>extern "C"</literal>-ként lett definiálva
	annak függvényneve szimbólumként használható akárcsak egy
	C függvénynek. Ezért csak nem-tagfüggvények deklarálhatók
        <literal>extern "C"</literal> segítségével, és ezeket nem lehet
	átdefiniálni.</para>
      
      <para>Habár van néhány megkötés az <literal>extern
        "C"</literal> függvényekre, mégis igen hasznosak, mivel dinamikusan
	betölthetőek a <function>dlopen</function> segítségével akárcsak
	a C függvények.</para>

      <para>Ez <emphasis>nem</emphasis> jelenti azt, hogy az 
      <literal>extern "C"</literal>-vel definiált függvények nem
      tartalmazhatnak C++ kódot. Az ilyen függvények teljes értékű C++ függvények,
      kihasználhatják a C++ lehetőségeit és bármilyen típusú argumentummal
      rendelkezhetnek.</para>

    </section>

    <section id="loadingfunctions">
      <title>Függvények betöltése</title>

      <para>C++ a függvények úgy tölthetőek be mint C-ben; a 
        <function>dlsym</function> segítségével. A betölteni kívánt
	függvényeket <literal>extern "C"</literal>-vel kell jelölnöd,
	hogy a C-szerű szimbólum névképzést kikényszerítsd.</para>

      <example>
        <title>Egy függvény betöltése</title>

        <para>main.cpp:</para>
        <programlisting><![CDATA[#include <iostream>
#include <dlfcn.h>


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

    cout << "C++ dlopen demo\n\n";

    // open the library
    cout << "Opening hello.so...\n";
    void* handle = dlopen("./hello.so", RTLD_LAZY);
    
    if (!handle) {
        cerr << "Cannot open library: " << dlerror() << '\n';
        return 1;
    }
    
    // load the symbol
    cout << "Loading symbol hello...\n";
    typedef void (*hello_t)();
    hello_t hello = (hello_t) dlsym(handle, "hello");
    if (!hello) {
        cerr << "Cannot load symbol 'hello': " << dlerror() <<
            '\n';
        dlclose(handle);
        return 1;
    }
    
    // use it to do the calculation
    cout << "Calling hello...\n";
    hello();
    
    // close the library
    cout << "Closing library...\n";
    dlclose(handle);
}
]]></programlisting>


        <para>hello.cpp:</para>
        <programlisting><![CDATA[#include <iostream>

extern "C" void hello() {
    std::cout << "hello" << '\n';
}
]]></programlisting>
      </example>

      <para>A <function>hello</function> függvény a 
        <filename>hello.cpp</filename> állományban van definiálva, mint
	<literal>extern "C"</literal>.
	A <filename>main.cpp</filename>-ben töltődik be a 
	<function>dlsym</function>
	hívással. A függvényt <literal>extern "C"</literal>-vel kell megjelölni,
	mert különben nem tudjuk biztosan a hozzá tartozó szimbólumnevet.
	</para>

      <warning>
        <para>Két típusa létezik az <literal>extern "C"</literal> 
	deklarációnak: <literal>extern
            "C"</literal> ahogy fent is használtuk, és <literal>extern "C" {
            &hellip; }</literal> a deklaráció kapcsos zárójelek között.
          Az első (inline) forma egy deklaráció ami egyszerre extern
          és C nyelvű kiértékelést ír elő, míg a második csak a nyelvi előírást
	  befolyásolja. Az alábbi két deklaráció ekvivalens:
          
          <informalexample>
            <programlisting>extern "C" int foo;
extern "C" void bar();
            </programlisting>
          </informalexample>
           és
          <informalexample>
            <programlisting>extern "C" {
     extern int foo;
     extern void bar();
 }</programlisting>
          </informalexample>

	  Ahogy nincs különbség 
          <literal>extern</literal> és a
          nem-<literal>extern</literal> <emphasis>függvény</emphasis>
          függvénydeklarációk között sem. 
	  Ez mindaddig nem jelent problémát amíg nem deklarálsz változókat.
	  Ha <emphasis>változókat</emphasis> deklarálsz tartsd észben, hogy

          <informalexample>
            <programlisting>extern "C" int foo;</programlisting>
          </informalexample>
            és
          <informalexample>
            <programlisting>extern "C" {
    int foo;
}</programlisting>
          </informalexample>
          
           <emphasis>nem</emphasis> ugyanaz a dolog.</para>
        
        <para>További részleteket találsz a 
          <citation>ISO14882</citation>, 7.5 fejezetében, 
          különös tekintettel a 7. bekezdésre
	  vagy a <citation>STR2000</citation>,
          9.2.4. paragrafusában.</para>

        <para>Mielőtt bármi extra dolgot csinálnál az extern változókkal,
	ajánlott elolvasni a &#8222;<link linkend="seealso">További információ</link>&#8221; 
	fejezetben felsorolt dokumentumokat.</para>

      </warning>

    </section>
    
    <section id="loadingclasses">
      <title>Osztályok betöltése</title>

      <para>Az osztályok betöltése egy kicsit komplikáltabb, mert
        nekünk az osztály egy <emphasis>példányára</emphasis>
	van szükségünk, nem csak egy függvényre mutató mutatóra.
        </para>

      <para>Nem tudjuk létrehozni az osztály egy példányát a 
        <literal>new</literal> operátor segítségével, mert
	az osztály nincs definiálva a futtatható állományban, és mert
	nem tudjuk a nevét.</para>

      <para>A megoldás a polimorfizmus segítségével adódik.
      Egy alap <emphasis>interfész</emphasis> osztályt definiálunk
      a <emphasis>futtatható állományban</emphasis> 
      virtuális tagfüggvényekkel, és egy származtatott
        <emphasis>implementációs</emphasis> osztályt 
	<emphasis>a modulban</emphasis>. Általában az interfész 
	absztrakt osztály (egy osztály absztrakt, ha minden függvénye
	virtuális).</para>

      <para>A dinamikus osztálybetöltést általában plug-in-okban  
      használják &mdash; Ezeknek egy világosan definiált interfészt kell
      használniuk &mdash; Egy interfészt és az azt implementáló osztályokat
      kell definiálnunk.</para>

      <para>Ezek után - még mindig a modulban - definiálunk két további
      segédfüggvényt (úgynevezett <emphasis>class factory 
      functions</emphasis>). 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 <literal>extern
          "C"</literal> direktívával jelöljük meg.</para>

      <para>Ahhoz, hogy osztályt tölts be modulból csak a két factory
      függvényt kell betöltened a <function>dlsym</function>
      segítségével. Szerkeszteni (link) ugyanúgy kell, mint ahogy azt <link
        linkend="loadingfunctions">ebben részben tettük a 
	hello függvénnyel</link>. Ezek után már
	annyi példányt tudsz létrehozni és felszabadítani az osztályból,
	amennyit csak akarsz.</para>

      <example>
        <title>Egy osztály betöltése</title>

        <para>Itt mi most egy általános <classname>polygon</classname>
          osztályt használunk, mint interfész és egy származtatott 
          <classname>triangle</classname> osztályt, mint implementációt.</para>

        <para>main.cpp:</para>
        <programlisting><![CDATA[#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);
}
]]></programlisting>

        <para>polygon.hpp:</para>
        <programlisting><![CDATA[#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
]]></programlisting>

        <para>triangle.cpp:</para>
        <programlisting><![CDATA[#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;
}
]]></programlisting>

      </example>

      <para>Néhány dolgot meg kell jegyeznünk az osztályok betöltésével
      kapcsolatban:</para>

      <itemizedlist>
        <listitem>
          <para>Az osztályt létrehozó és felszabadító függvényeket <emphasis>meg kell írnod</emphasis>.
	  Soha <emphasis>ne</emphasis> szabadítsd fel a példányokat a
            <literal>delete</literal> operátorral a futtatható állományon
	    belül. Mindig add vissza azokat a modulnak.
	    Ez azért szükséges, mert a <literal>new</literal> és a
            <literal>delete</literal> C++ operátorok 
	    használata nem feltétlenül konzekvens. Ezért lehetséges, hogy egy pár nélküli
            <literal>new</literal> vagy
            <literal>delete</literal> hívás az oka a memória-szivárgásnak vagy
            segmentation fault-nak.
	    Ugyanez igaz akkor is, ha különböző standard programkönyvtárakat használsz a modulban és futtatható állományban.</para>
        </listitem>

        <listitem>
          <para>Az interfész osztály dekonstruktorának virtuálisnak
	  kell lennie szinte minden esetben. <emphasis>Lehetséges</emphasis>
	  egy meglehetősen ritka eset, amikor ez nem feltétlen szükséges.
	  Ez a megkötés nem okoz problémát, mert az általa keletkező többletterhelés (overhead)
	  elhanyagolható.</para>
          <para>Ha az alap osztályodnak nincs szükséges dekonstruktorra
	  akkor is definiálj egy üreset (és <literal>virtual</literal>-t),
	  különben előbb vagy utóbb <emphasis>problémáid lesznek</emphasis>.
	  Ezt garantálom. Többet tudhatsz meg erről a problémáról 
          a <ulink url="http://www.parashift.com/c++-faq-lite/">C++ FAQ lite</ulink> webhelyen található comp.lang.c++ GYIK 20. fejezetéből.</para>
        </listitem>
      </itemizedlist>

    </section>
  </section>

  <section id="faq">
    <title>Gyakran Ismételt Kérdések</title>
    <qandaset>
      <qandaentry>
        <question>
          <para>Windowst használok és nem találom a 
          <filename>dlfcn.h</filename> header állományt a PC-men! 
	  Mi a probléma?</para>
        </question>
        <answer>
          <para>A probléma, mint mindig a Windows. Nincs 
	  <filename>dlfcn.h</filename> header Windows-on és nincs
          <function>dlopen</function> API sem. Van egy hasonló
	  API a <function>LoadLibrary</function> függvénnyel.
	  A legtöbb itt leírt dolog alkalmazható erre is.
	  Továbbá használhatod a libltdl (a libtool része) programkönyvtárat, hogy 
          <quote>emuláld</quote> a <function>dlopen</function>-t
	  számos platformon.</para>

          <para>Olvasd el a <ulink url="http://tldp.fsf.hu/HOWTO/Program-Library-HOWTO-hu/index.html">Programkönyvtár HOGYAN</ulink> (<ulink url="http://www.dwheeler.com/program-library">Program Library HOWTO</ulink>) 4. fejezetét (<ulink url="http://tldp.fsf.hu/HOWTO/Program-Library-HOWTO-hu/dl-libraries.html">Dinamikusan betölthető (Dynamically Loaded; DL) programkönyvtárak</ulink>; <ulink url="http://www.dwheeler.com/program-library/Program-Library-HOWTO/dl-libraries.html">Dynamically Loaded (DL) Libraries</ulink>). Ez további információkkal szolgál olyan
	    technikákról, amelyekkel platformfüggetlenül tölthetsz be
	    programkönyvtárakat és készíthetsz osztályokat.</para>
        </answer>
        </qandaentry>

      <qandaentry>
	<question>
	  
	  <para>Létezik bármilyen <function>dlopen</function>-kompatibilis
	    illesztőfelület a Windows <function>LoadLibrary</function>
	    API-jához?</para>
	  
        </question>
	<answer>
	  
	  <para>Nem tudok róla és nem hiszem, hogy valaha is lesz olyan, ami
	  a <function>dlopen</function> összes lehetőségét támogatni
	  fogja.</para>
	
	  <para>Vannak alternatív megoldások: libtltdl (a libtool része),
	    ami a különböző dinamikus betöltő API-khoz nyújt egységes
	    felületet, köztük a <function>dlopen</function> és a 
	    <function>LoadLibrary</function> API-khoz is.  
	    Egy másik lehetőség a <ulink url="http://developer.gnome.org/doc/API/glib/glib-dynamic-loading-of-modules.html">
	      Dynamic Loading of Modules</ulink> (A GLib dinamikus modul betöltés).  
	      Használd ezeket a jobb platformfüggetlenség biztosítása érdekében.
	     Én soha nem használtam őket, így nem tudom megmondani neked mennyire
	     stabilak és hogyan működnek.</para>
        </answer>
      </qandaentry>
    </qandaset>
  </section>

  <section id="seealso">
    <title>További információ</title>

    <itemizedlist>
      <listitem>
        <para>A <function>dlopen(3)</function> kézikönyv oldalai. 
	  Ez kifejti a <function>dlopen</function> API célját és a használatát.
          </para>
      </listitem>

      <listitem>
        <para>A <ulink
            url="http://www.linuxjournal.com/article.php?sid=3687">
            <citetitle>Dynamic Class Loading for C++ on
              Linux</citetitle></ulink> cikk James Norton tollából a
          <ulink url="http://www.linuxjournal.com/">Linux
            Journal</ulink>-on.</para>
      </listitem>

      <listitem>
        <para>A kedvenc C++ referenciád a <literal>extern
            "C"</literal>-ról, öröklődésről, virtuális függvényekről,
          <literal>new</literal> és <literal>delete</literal>
	  operátorokról. A <citation>STR2000</citation> ajánlott.</para>
      </listitem>

      <listitem>
        <para><citation>ISO14882</citation></para>
      </listitem>

      <listitem>
        <para>A <ulink url="http://tldp.fsf.hu/HOWTO/Program-Library-HOWTO-hu/index.html">Programkönyvtár HOGYAN</ulink> (<ulink
            url="http://www.dwheeler.com/program-library">Program Library
            HOWTO</ulink>) mintent tartalmaz,
	    amire valaha szükséged lesz statikus, megosztott és dinamikusan
	    betölthető programkönyvtárakkal kapcsolatban. Melegen ajánlott.
            </para>
      </listitem>

      <listitem>
        <para>A <ulink
            url="http://tldp.org/HOWTO/GCC-HOWTO/index.html">Linux GCC
            HOWTO</ulink>-ból többet tudhatsz meg arról, hogyan készíthetsz
	    programkönyvtárakat GCC-vel.</para>
      </listitem>

    </itemizedlist>

  </section>

  <bibliography>

    <bibliomixed>
      <abbrev>ISO14482</abbrev> <title>ISO/IEC 14482-1998 &mdash; The
        C++ Programming Language</title>. <releaseinfo>PDF és nyomtatott
	könyv formájában is elérhető a <ulink
          url="http://webstore.ansi.org/"/> webhelyen.</releaseinfo>
    </bibliomixed>

    <bibliomixed>
      <abbrev>STR2000</abbrev>
      <author><surname>Stroustrup</surname>
        <firstname>Bjarne</firstname></author>
      <title>The C++ Programming Language</title>, <edition>Special
        Edition</edition>.
      ISBN <isbn>0-201-70073-5</isbn>.
      <publishername>Addison-Wesley</publishername>.
    </bibliomixed>

  </bibliography>

</article>


