Sława!
Dziś chciałbym jakże szanownym Czytelniczkom i Czytelnikom zaprezentować parę wskazówek jak pisać własne biblioteki/pliki nagłówkowe dla NSIS. Po cóż, a po coż to się męczyć z czymś takim? - zapyta ktoś bardziej marudny. Ha! Otóż marudo moja kochana, po piersze primo zawsze warto wydzielać sobie wieloużywalne kawałki własnego kodu, żeby potem nie wymyślać koła po raz kolejny. A po drugie primo, w wypadku NSISa główny plik projektu przy większej komplikacji ma tendencje do bardzo szybkiego rozrostu, toteż pogubienie się w kodzie jest tylko kwestią czasu. I właśnie aby czas ten wydłużyć warto jednak powydzielać sobie funkcję do bibliotek.
Od czego zacząć? Wydaje mi się, że od wydzielenia, przynajmniej koncepcyjnie, tego co chcemy sobie zamknąć w funkcję w ramach biblioteki (a może bibliotek), oraz wymyśleniu sobie nazw zarówno dla funkcji, jak i dla biblioteki. Należy pamiętać, że nie powinny być zbyt lakoniczne, ani też za długie, bo na dzień dzisiejszy narzędzia wspierające pisanie w NSIS nie podpowiadają składni zawartej w bibliotekach. Jeżeli już wymyśliliśmy sobie to i owo, możemy przystąpić do dzieła (a może nawet Dzieła).
Załóżmy, że nową bibliotekę nazwaliśmy sobie PNG (od Przebłysk Naszego Geniuszu) i zawierać będzię ona jedną funkcję o nazwie, jakżeby inaczej, Funkcja. Jedną bo ma posłużyć za przykład, kolejne sobie możemy dorobić już siłą rozpędu. Dodajmy także, że będziemy chcieli jej używać zarówno w instalatorach jak i deinstalatorach.
Zaczynamy więc od następujacego szkieletu:
!ifndef PNG !define PNG !verbose push !verbose 3 !ifndef PNG_DELIM !define PNG_DELIM '.' !endif !ifndef PNG_UN !define PNG_UN !endif #Includes !ifndef NFUPREFIX !include nfUtils.nsh !endif #Installer----------------------------------------------------------------------------------------- #Callers----------------------------------------- #Bodies------------------------------------------ #Unistaller---------------------------------------------------------------------------------------- #Callers----------------------------------------- #Bodies------------------------------------------ !verbose pop !endif
Gdzie, PNG_DELIM określa delimiter między nazwą biblioteki, a nazwą funckji - przyjąłem założenie, że używać będziemy ich w sposób podobny do nsArray, czyli poprzez zapis ${PNG.Funkcja}. Definicja PNG_UN jest podstawą pewnej sztuczki przy wspieraniu deinstalatorów, o czym później może parę słów (Ale niczego nie obiecuję). W sekcji #Includes dodajemy niezbędne polecenia include dołączające zewnętrzne biblioteki (np. LogicLib). Warto dołączać je tutaj, żeby być pewnym, że żadnej nie zabraknie. Włączona tu została biblioteka nfUtils, wspomagająca tworzenie własnych bibliotek. Wreszcie sekcje #Callers zawierać będą "wołacze" do funkcji, czyli to co umożliwi użycie wspomnianego zapisu ${PNG.Funkcja}, a #Bodies już właściwe ciała funkcji.
Uzupełnijmy więc te sekcje dla cześci "instalacyjnej":
#Callers----------------------------------------- ;Funkcja ; ;parametr ; parametr ; ;zwraca ; wynik !macro PNG${PNG_DELIM}Funkcja_Call _parametr _wynik Push ${_parametr} Call PNG${PNG_DELIM}Funkcja Pop ${_wynik} !macroend #Bodies------------------------------------------ !macro PNG${PNG_DELIM}Funkcja !ifndef ${PNG_UN}PNG${PNG_DELIM}Funkcja !define ${PNG_UN}PNG${PNG_DELIM}Funkcja '!insertmacro ${PNG_UN}PNG${PNG_DELIM}Funkcja_Call' ;$1 - wynik ;$0 - parametr ${nfu.Function} ${PNG_UN}PNG${PNG_DELIM}Funkcja in $0 out $1 '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' # Ciało funkcji ${nfu.FunctionEnd} !endif !macroend
W ciale funkcji w $0 znajdzie się przekazywany parametr, natomiast zawartość $1 przy wyjściu z funkcji będzie umieszczona na stosie. Po zakończeniu funkcji wartości $0 i $1 będą takie same jak przed jej wykonaniem. Jeżeli chcemy używać w ciele innych zmiennych $0-9 należy samemu obsłużyć podobne zachowanie za pomocą operacji na stosie.
Zostało więc uzupełnienie sekcji dla deinstalatora, tu już chyba nie ma większej magii:
#Callers----------------------------------------- !macro un.PNG${PNG_DELIM}Funkcja_Call _parametr _wynik Push ${_parametr} Call un.PNG${PNG_DELIM}Funkcja Pop ${_wynik} !macroend #Bodies------------------------------------------ !macro un.PNG${PNG_DELIM}Funkcja !undef ${PNG_UN} !define ${PNG_UN} 'un.' !insertmacro PNG${PNG_DELIM}Funkcja !undef ${PNG_UN} !define ${PNG_UN} !macroend
I to było by na tyle. Wnikliwsza analiza, wykaże, że cała zabawa polega na sprytnym wykorzystaniu poleceń preprocesora NSIS do wpływania na proces generowania "wynikowego" źródła do kompilacji, podkładając mu odpowiedni kod w miejsce używanych definicji. Dlatego też, możemy używać naszej biblioteki podobnie jak LogicLib czy nsArray poprzez ${PNG.Funkcja} 'parametr' $Wynik
Brak komentarzy:
Prześlij komentarz