user:skripty:dlls
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
user:skripty:dlls [2010/12/14 10:20] – mikrom | user:skripty:dlls [Unknown date] (current) – external edit (Unknown date) 127.0.0.1 | ||
---|---|---|---|
Line 7: | Line 7: | ||
Překladač pak nebude hledat ve skriptu implementaci funkce a v případě potřeby zavolá příslušnou funkci v DLL knihovně. | Překladač pak nebude hledat ve skriptu implementaci funkce a v případě potřeby zavolá příslušnou funkci v DLL knihovně. | ||
+ | |||
+ | <WRAP tip> | ||
Příklad: | Příklad: | ||
<code delphi> | <code delphi> | ||
- | function FindWindow(C1, | + | function FindWindow(C1, |
- | function ShowWindow(hWnd, | + | function ShowWindow(hWnd, |
- | function SetWindowText(hWnd: | + | function SetWindowText(hWnd: |
procedure something; | procedure something; | ||
- | var | + | var |
- | i: Longint; | + | i: longint; |
- | wnd: Longint; | + | wnd: longint; |
- | Begin | + | begin |
wnd := Findwindow('', | wnd := Findwindow('', | ||
SetWindowText(Wnd, | SetWindowText(Wnd, | ||
Line 29: | Line 31: | ||
for i := 0 to 200000 do begin end; | for i := 0 to 200000 do begin end; | ||
SetWindowText(Wnd, | SetWindowText(Wnd, | ||
- | End; | + | end; |
</ | </ | ||
===== Vyzkoušené deklarace Windowsích funkcí z knihoven ===== | ===== Vyzkoušené deklarace Windowsích funkcí z knihoven ===== | ||
<code delphi> | <code delphi> | ||
- | function GetShortPathName(lpszLongPath, | + | function GetShortPathName(lpszLongPath, |
- | function GetShortPathNameLength(lpszLongPath: | + | function GetShortPathNameLength(lpszLongPath: |
function GetShortName(value: | function GetShortName(value: | ||
Line 42: | Line 44: | ||
begin | begin | ||
l := GetShortPathNameLength(value, | l := GetShortPathNameLength(value, | ||
- | | + | |
l := GetShortPathName(value, | l := GetShortPathName(value, | ||
- | | + | |
end; | end; | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | ====== Vytvoření DLL knihovny pro použití v GeoGetu ====== | ||
+ | |||
+ | Vytvoření knihovny v Delphi asi nebude dělat velké problémy, ale pro knihovnu vytvářenou v C++ je třeba si uvědomit odlišnosti mezi Delphi a C++. Jde zejména: | ||
+ | |||
+ | * o dekorování jmen funkcí | ||
+ | * o konvenci volání funkcí | ||
+ | |||
+ | Demonstrovat řešení budu na Microsoft Visual Studiu (já konkretně mám verzi 2010). U jiných verzí MSVC to bude podobné a analogie se najde jistě u jiných kompilátorů - když se ví, co hledat, je to jednodušší. | ||
+ | |||
+ | <WRAP tip>Pro použití knihovny je nutné, aby byla uložená tam, kde ji bude systém hledat, tedy na jednom z těchto míst: | ||
+ | |||
+ | - v některém z vhodných systémových adresářů (např \Windows\SysWOW64) | ||
+ | - v adresáři, který je uveden v systémové proměnné PATH (samozřejmě je možné tuto proměnnou upravit) | ||
+ | - v adresáři, kde je exe soubor, který knihovnu používá (v našem případě GeoGet.exe) | ||
+ | - v aktualním (pracovním) adresáři, zde bz to byl DATADIR | ||
+ | - upravit impor funkce a doplnit jméno knihovny o relativní cestu (vůči DATADIR) k ní, např. | ||
+ | '' | ||
+ | |||
+ | Doporučoval bych některou z posledních tří možností. | ||
+ | </ | ||
+ | |||
+ | ===== Dekorování jmen funkcí ===== | ||
+ | Standardně C/C++ používá pro jména funkcí tzv. zdobení mebo dekorování. To znamená, že jméno funkce je obaleno nějakými znaky, které mj. linkeru slouží pro kontrolu typu funkce a počtu parametrů. Protože Delphi žádné zdobení nepoužívá, | ||
+ | |||
+ | Napřed tedy vytvoříme soubor '' | ||
+ | |||
+ | < | ||
+ | LIBRARY | ||
+ | EXPORTS | ||
+ | SoucetInt | ||
+ | SoucetStr | ||
+ | </ | ||
+ | |||
+ | a přikážeme jeho použití: '' | ||
+ | |||
+ | Pochopitelně je potřeba také funkce správně exportovat, např. | ||
+ | |||
+ | <code C++> | ||
+ | |||
+ | #define LIB_EXPORT __declspec(dllexport) | ||
+ | #define LIB_IMPORT __declspec(dllimport) | ||
+ | |||
+ | LIB_EXPORT LPCSTR SoucetStr(LPCSTR s1, LPCSTR s2){ | ||
+ | CString sa,sb; | ||
+ | sa=CString(s1); | ||
+ | sa=sa+sb; | ||
+ | return(sa); | ||
+ | }; | ||
+ | |||
+ | LIB_EXPORT int SoucetInt(int i1,int i2){ | ||
+ | return(i1+i2); | ||
+ | }; | ||
+ | </ | ||
+ | |||
+ | Pokud by mely být funkce použité ve vlastní aplikaci C/C++, musí být naopak z knihovny správně importované: | ||
+ | |||
+ | <code C++> | ||
+ | |||
+ | LIB_IMPORT LPCSTR SoucetStr(LPCSTR s1, LPCSTR s2); | ||
+ | LIB_IMPORT int SoucetInt(int i1,int i2); | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | ===== Konvence volání funkcí ===== | ||
+ | Když máme správně pojmenované funkce v knihovně, můžeme se vrhnout na jejich volání. | ||
+ | Implicitní volání v C/C++ je typu '' | ||
+ | |||
+ | * přizpůsobit plugin | ||
+ | * přizpůsobit knihovnu | ||
+ | |||
+ | ==== Přizpůsobení pluginu ==== | ||
+ | Tato cesta mi připadá výrazně jednodušší a nemá navíc žádný další vliv na přípanou C/C++ aplikaci, která by táké tuto knihovnu používala. Řešení spočívá pouze v tom, že překladači pluginu přikážeme typ '' | ||
+ | |||
+ | <code delphi> | ||
+ | function SoucetInt(i1, | ||
+ | function SoucetStr(s1, | ||
+ | </ | ||
+ | |||
+ | ==== Přizpůsobení knihovny ==== | ||
+ | Pro přizpůsobení knihovny je třeba změnit implicitní nastavení kompilátoru: | ||
+ | |||
+ | '' | ||
+ | | ||
+ | a v souladu s ním deklarovat funkce v pluginu: | ||
+ | |||
+ | <code delphi> | ||
+ | function SoucetInt(i1, | ||
+ | function SoucetStr(s1, | ||
+ | </ | ||
+ | |||
+ | Pokud takto změníte volací konvenci a knihovnu použijete také ve své vlastní aplikaci vytvořené v C/C++, je na to třeba pamatovat a knihovní funkce použít správně. | ||
+ | |||
+ | |||
+ | |||
+ | ===== Přebírání parametru typu string z DLL knihovny ===== | ||
+ | |||
+ | <WRAP important> | ||
+ | |||
+ | * knihovní funkce má navíc 2 parametry: adresu textového bufferu a jeho alokovanou velikost | ||
+ | * místo aby funkce vracela string, zápíše string do bufferu a vrátí počet zapsaných znaků | ||
+ | |||
+ | Takže s ohledem na výše řečené bude plugin obsahovat něco takovéhoto: | ||
+ | |||
+ | <code delphi> | ||
+ | //deklarace knihovní funkce | ||
+ | function SoucetStr(s1, | ||
+ | ... | ||
+ | |||
+ | //volání a převzetí vráceného textu | ||
+ | const MAX_BUFR_LENGTH=256; | ||
+ | |||
+ | var sBuffer: | ||
+ | // !! bude na konci sBuffer obsahovat prazdny text, | ||
+ | // !! protoze 1. byt znaku bude mit hodnotu 0 | ||
+ | // !! a to bude chapano jako konec textu | ||
+ | iLen: | ||
+ | begin | ||
+ | ... | ||
+ | SetLength(sBuffer, | ||
+ | iLen: | ||
+ | SetLength(sBuffer, | ||
+ | ... | ||
+ | end; | ||
+ | </ | ||
+ | |||
+ | a funkce v DLL knihovně může vypadat třeba nějak takto: | ||
+ | |||
+ | <code C++> | ||
+ | LIB_EXPORT int SoucetStr(LPCSTR s1, LPCSTR s2, LPSTR sBuffer, int iMaxLen){ | ||
+ | CString cs=CString(s1)+CString(s2); | ||
+ | strcpy_s(sBuffer, | ||
+ | return(strlen(sBuffer)); | ||
+ | } | ||
</ | </ |
user/skripty/dlls.1292318438.txt.gz · Last modified: 2010/12/14 00:00 (external edit)