Diskuze: DLL knihovny
Člen
Zobrazeno 21 zpráv z 21.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
Ahoj, moc věcí o tom nevím , také bych rád věděl o tom víc. Pokusím se to přiblížit s mými znalostmi. DLL - (Dynamic-link library) soubory mohou být třeba (nevím jestli je to správně - odvodil jsem si to ) databáze, rozšíření programů, activex ... některé se dají otevřít otevřít v programech - ty co používám já: dotPeek, Resource hacker ...
Jinak se to dá i určitě "gůglit" tak pro příště
např. http://cs.wikipedia.org/wiki/DLL
V podstatě je to jen balík tříd a metod. Pokud bys například udělal několik tříd pro práci s řetězci, tak si je můžeš zabalit do knihovny a pak je pomocí té knihovny používat v dalších aplikacích.
DLL knihovna je uvnitr v podstate to same, co EXE - jen nejaky kod, ktery spoustis.
Rozdil je v tom, jak ten kod spoustis - kod v EXE se spousti spustenim toho EXE, knihovnu musis nejdriv nahrat do nejakeho EXE, aby jsi jeji kod mohl pouzivat.
Úplně jsem nepochopil tvoji otázku
takže s tím můžu okopčit kus programu nebo proměnou
Volací konvence je jak mezi sebou ta aplikace a knihovna komunikují - jak si předávají parametry a výsledky funkcí - jestli třeba přes zásobník nebo přes registry, jejich pořadí apod...
Je zbytečné mít stejný kód ve více aplikacích, tak se ta společná
část kódu vytrhne a dá do DLL.
V aplikacích ti pak stačí mít jen odkaz na tu společnou knihovnu a načteš
ji až při spuštění aplikace.
Volací konvence - DLL funkci se předávají parametry přes zásobník. Po ukončení funkce je potřeba parametry ze zásobníku odstranit. U volací konvence C parametry odstraňuje volající funkce (např.: PUSH EAX uloží registr EAX do zásobníku jako parametr, CALL XXX zavolá volanou funkci a ADD ESP,4 posune ukazatel zásobníku a tím parametr odstraní).
U volací konvence Pascal odstraňuje parametry volaná funkce - to znamená že musí posunout ukazatel zásobníku a teprve až potom se vrátit do volané funkce. Nevýhodou konvence Pascal je dost krkolomná práce se zásobníkem (musí si uchovat ze zásobníku návratovou adresu než parametry zruší), mezi volanou a volající funkci nelze vsunout odbočku na jinou funkci (protože by přidala svou návratovou adresu a tím by narušila strukturu zásobníku) a volaná funkce musí znát počet parametrů, což nelze použít u funkcí s proměnlivým počtem parametrů (jako např. printf).
Jedinou výhodou konvence Pascal je malá úspora velikosti programu používajícího DLL knihovnu. Zřejmě proto tuto konvenci Microsoft (dost nešťastně) zvolil u DLL knihoven. Interně ale programy i DLL knihovny používají C konvenci. Většinou lze ponechat implicitní volání Pascal, protože se u DLL téměř všude používá. Pokud by byla konvence špatně zvolena, projeví se to pravděpodobně chybnou funkcí a tvrdou havárií programu.
Měl bych prosím dotaz k volání funkce z DLL s více parametry. Nevím jestli předávám parametry funkce správně do paměťového bloku. Postupuji následovně - nejprve importuji funkci z DLL pomocí k tomu určené funkce, zadám počet parametrů a konvenci C na Ano. Importovací funkce mi vrátí adresu paměťového bloku. A pak před voláním této importované funkce uložím za sebe její parametry na adresu pam. bloku zvýšenou o 8B. Čili nastavím na tuto adresu ukazatel zápisu a uložím všechny parametry jako "dvouslovo se znaménkem", jelikož parametry jsou všechny typu int. Parametry ukládám ve stejném pořadí jak jsou uvedeny u deklarace funkce v knihovně. A tady právě trochu tápu. Jestli nemají být parametry uloženy v obráceném pořadí. Už úspěšně používám funkce bez parametrů a ty mi fungují. Takže nějaké zkušenosti s tím už mám.
To záleží, jak je funkce, kterou chcete volat, v dané DLL knihovně definována, zejména jakou má volací konvenci. Tu se dozvíte z hlaavičkového souboru, který by měl být dodáván ke knihovně.
Na 32bitových Windows se obvykle používá stdcall, která, jestli dobře chápu váš příspěvek, se velmi podobá tomu, co děláte, jen parametry na zásobník ukládá zprava doleva, ne zleva doprava.
Na 64bitových Windows se používá fastcall, která předává první čtyři parametry v registrech (RCX, RDX, R8, R9), zbytek na zásobníku. Je tam ještě něco o tom, že musíte vyhradit na zásobníku i místo pro ty první čtyři.
Obecně ale záleží na dané DLL knihovně. Není třeba problém používat konvenci cdecl, pascal či jakoukoli jinou.
Ve své knihovně používám konvenci cdecl, která je výchozí pro projekty ve Visual C++ 6.0. Mám nastavené __cdecl v Project Settings v kategorii "Code Generation" u "Calling convention". Zkoušel jsem nastavit __stdcall, ale tam dochází k dekorování jmen funkcí (_jmenofunkce@pocetbajtuparametru). Takže mi přestaly funkce z knihovny v Petrovi chodit úplně. Když jsem si tu jednu fci s parametry správně přejmenoval podle té stdcall konvence, tak se Petr hned po volání fce ukončil.
Musíte zjistit, jakou volací konvenci Petr pro funkce z DLL knihoven používá, a tu použít ve své knihovně (případně v Petra k dané konvenci donutit).
Ano, stdcall dekoruje jména funkcí, ale lze tomu předejít napsáním vlastního DEF souboru pro knihovnu. Jinak řečeno, název funkce exportované knihovnou sám o sobě o její volací konvenci nic nevypovídá.
Podle nápovědy k Petrovi, pokud nastavím při importu funkce volací konvenci C na "Ano", tak by to mělo zřejmě odpovídat konvenci cdecl, čili až po návratu z funkce jsou zrušeny parametry ze zásobníku. Pokud se nastaví volací konvence C na "Ne", tak by se měla použít konvence Pascal, čili o zrušení parametrů ze zásobníku se stará volaná funkce. V nápovědě se dále píše, že "první parametr je při volání funkce uložen na nejnižší adrese zásobníku". A jelikož zásobník roste od vyšších adres k nižším, tak to znamená, že první parametr by se měl tedy uložil až jako poslední. Dále je ale v nápovědě toto: "Před voláním funkce je nutno nastavit parametry funkce. Implicitně jsou všechny parametry při importování funkce inicializovány na nulu. Nastavení parametrů se provádí pomocí následujících operací pro manipulaci s paměťovými bloky. První parametr je umístěn na offsetu 8 od začátku paměťového bloku." Tady se zřejmě prvním parametrem myslí obecně první ukládaný parametr a ne první parametr v pořadí, jak jdou za sebou v deklaraci funkce.
Tak už mám jasno. Parametry funkce se musí uložit před voláním funkce ve stejném pořadí, jako jsou ve funkci. Tak jak jsem psal výše v tom prvním příspěvku. Přidal jsem si do knihovny jednoduchou testovací funkci, kterou jsem si to ověřil:
int TestFunction(int a, int b)
{
return a;
}
Když uložím do pam. bloku parametry s hodnotami např. 1 a 2, tak mi funkce vrací hodnotu 1.
Zobrazeno 21 zpráv z 21.