hlmod.hu
https://hlmod.hu/

AmxModX Alapozó 06. - Függvények
https://hlmod.hu/viewtopic.php?f=55&t=17025
Oldal: 1 / 2

Szerző:  Metal [ 2014.08.19. 11:30 ]
Hozzászólás témája:  AmxModX Alapozó 06. - Függvények

Függvények

A függvények rejtelmeibe vezetlek be benneteket. Mire jók, miért szeretjük, hogyan használjuk? (A tutort a komolyabb fogalomzavarban szenvedőknek ajánlom, akik nem tudják mi a fene a stock.... ez elég gáz. Gondolok erre: "stockot a végére s kész".)
Még sok mindent le lehetne írni, de ezt maximum a hszek alapján fogom megtenni, (tehát felmerült kérdések esetén bővítem)
Az előbbiekkel ellentétben ez nem annyira referenciásnak készült.

Bevezetés
Mikor kódot írunk, akkor egy nagyobb feladat megoldása is nehézkes, és átláthatatlan, ha az alap belépési ponthoz rendelt (jelen esetben plugin_init) függvénybe írnánk. Képzeljünk el egy több ezer soros kódot, aminek minden egyes sora plugin_initben van! Kezelhetetlen (meg a scriptelők esetében felfoghatatlan, hiszen az csak az alap változó értékek beállítására és az eseményekre való feliratkozásra + parancsok létrehozására használjuk)

A kód tisztává tételére definiálhatunk függvényeket, amik sok esetben könnyebbé teszik a kódolást. Ezeket több fajta kulcsszóval is el tudunk látni s ezáltal kiterjeszthetjük a funkcionalitásukat. Ilyen a public, native és a stock. Ezekről a fejezet végén olvashattok.

Szintaxis
Mindegyiknek megvan a maga szerepe a nyelvben. Mielőtt sorra vennénk, vegyük a függvény szintaxisát (általános, az alap Pawn kicsit többet tud, de az itt nem lényeges, itt nincs minden funkció kivezetve).

SMA Forráskód: [ Mindet kijelol ]
  1. [public|native|stock] functionName( [param_1, param_2, ....] ) {
  2. ...
  3. [return [X1]]
  4. ...
  5. [return [X2]]
  6. ...
  7. [return [XN]]
  8. }

Ahol param_x paraméterek skalárok, vagy tömbök vagy ezek egy kombinációja, míg az X1, X2, ..., XN a függvény visszatérési értéke. Ezek mind opcionálisak (maga a visszatérési érték is!).
Maga a függvény pozíciója, a helye a kódban teljesen irreleváns: Bárhova beírhatjuk a kódunkat, nem kell előre definiálni a létét, mint C++ban.

Példák
Egy nagyon egyszerű "Hello World!" loggoló függvény:

SMA Forráskód: [ Mindet kijelol ]
  1. show()
  2. {
  3. log_amx("Hello World!");
  4. }


Természetesen paramétereket is átadhatunk neki:

SMA Forráskód: [ Mindet kijelol ]
  1. show(count)
  2. {
  3. new i = 0;
  4. while (i < count) {
  5. log_amx("Hello World!")
  6. i++;
  7. }
  8. }


Ez a paraméterben megadott mennyiségű üzenetet log-gol majd.

Eljárás vagy függvény?
Amennyiben nincs return megadva, akkor eljárásnak hívjuk a "függvényt". Ez matek: A függvény visszaad egy értéket. itt is erről van szó. Ha nem ad vissza, akkor az már nem függvény :) Ennek ellenére a filozófia csak függvényként hivatkozik rá, azaz "minden függvény".
A legtöbb programozási nyelvekben ez máshogy van kezelve:
1) vagy van hozzá megfelelő kulcsszó (pl, Delphi, Pascal, Ada, VB: PROCEDURE és FUNCTION kulcsszavak)
2) vagy a visszatérési érték típusával azonosítjuk, hogy függvény-e (pl C, C++, C#, Java: void fgv() <- procedure, [int, byte, char, short, ...] fgv <- function).
Amennyiben a Pawnban a függvényt taggel látjuk el (pl Float:), akkor megadtunk neki egy visszatérési értéktípust, tehát ez már függvényként fog működni.

A Pawn fordító ezt kezeli is: Amennyiben van legalább egy return kulcsszó, akkor függvényként regisztrálja be, és visszajelez, ha nem minden ágban tér vissza. Ez a szokásos warning. Hibát nem okoz, csak akkor okozhat, ha függvényként használjuk.

Példa
SMA Forráskód: [ Mindet kijelol ]
  1. public mokas(i) {
  2. if (i)
  3. return i;
  4. }

Az is megeshet, hogy egy függvény futását csak megszakítani akarjuk s nem is várunk értéket vissza a függvénytől. Ezt megtehetjük a return kulcsszó megadásával:

SMA Forráskód: [ Mindet kijelol ]
  1. byebye(i)
  2. {
  3. if (i)
  4. return;
  5. else
  6. log_amx("Byebye");
  7. }


Függvényhívás
Amikor megírtunk egy függvényt, akkor használni is szeretnénk. Ehhez csupán meg kell adni a függvény nevét, (amit hívni akarunk), és zárójelben a paramétereit.

Példák
SMA Forráskód: [ Mindet kijelol ]
  1. // Példa 1:
  2. show(10); // Kiírja 10-szer, hogy "Hello World!"
  3.  
  4. // Példa 2:
  5. new k = mokas(10); // Visszaadja kb a 10-et.

Kérdések, nektek, mint Házi feladat ( :) ):
- Mi van akkor, ha new k = mokas(0) -át írunk be?
- Mi van akkor, ha csak ennyit írunk: mokas(10)

Paraméterezés
A függvényben alapértelmezetten a paraméterek érték szerint adódnak át, azaz a híváskor lemásolódnak az értékeik újra, s a függvény futása végén ezt törli. Az eredeti értékek sosem változnak meg.

Példa
SMA Forráskód: [ Mindet kijelol ]
  1. swap(a, b) {
  2. new tmp = a;
  3. a = b;
  4. b = tmp;
  5. }
  6.  
  7. new a = 10;
  8. new b = 20;
  9. swap(a, b);
  10. log_amx("a: %d, b: %d", a, b); // Eredmény: a: 10, b: 20

Erre megoldásként használható a referenciajel, amivel referencia (cím szerinti) értékadás fog történni. Nem foglal le a memóriában új helyet a paraméterben megadott változóknak, s nem másolja át a tartalmát. Egyszerűen a memóriabeli címét adja át, s az memóriacímre mutató értéket változtatja.

Előző kód "javítása":
SMA Forráskód: [ Mindet kijelol ]
  1. swap(&a, &b) {
  2. new tmp = a;
  3. a = b;
  4. b = tmp;
  5. }
  6.  
  7. new a = 10;
  8. new b = 20;
  9. swap(a, b);
  10. log_amx("a: %d, b: %d", a, b); // Eredmény: a: 20, b: 10

Tömb paraméterek
Lehetőség van tömböt is átadni paraméterül, viszont ezek mindig referencia szerint adódnak át. Ennek oka igen egyszerű: nem lehet tudni, hogy mekkora a tömb mérete, s nem feltétlen biztos az, hoyg lesz elég hely a híváskor. Emiatt adódik át cím szerint a cucc:

SMA Forráskód: [ Mindet kijelol ]
  1. duplicateNums(num[], size) {
  2. new i = 0;
  3. while (i < size) {
  4. num[i:7q0wa6te] *= 2;
  5. ++i;
  6. }
  7. }
  8.  
  9. new num[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  10. duplicateNums(num, sizeof(num));

Ha ezt el akarjuk kerülni, akkor a jól ismert const kulcsszóval tudjuk ezt jelölni, s ekkor fordítási időben jelzi felénk a hibát.

További kulcsszavak
Mire is vannak a korábban említett (public, native, stock) kulcsszavak (amiket használni nem kötelező)? Mindenekelőtt kicsit mélyedjünk el abban, hogy mi van a függvények mögött.

Bevezetés
Az AmxModX egy absztrakt (inkább virtuális) gép, ami beállítástól függően több különböző plugint tölt be. A pluginok többsége regisztrálhat parancsokat, mint például a /rank, /me, stb.
Ezek többségét a register_clcmd-vel tehetjük meg, (használhatunk register_concmd-t is, s akkor szerver konzolból is kiadható a móka).
Feliratkozhatunk eseményekre is (event, pl DeathMessage, Player[Pre/Post]Think, Spawn, LogeventRound, stb), amik az adott esemény triggelerése esetén futnak le.

Public
Ezen függvények megírásakor maga a motor hív be a pluginba, s keresi meg a lefordított plugin által küldött szimbólumtáblán a parancshoz/eseményhez rendelt függvényt. Ebben a táblában csakis a publikus függvények vannak jelen, ezek érhetőek el. innen adódik, hogy minden eseményre feliratkozni kívánt függvénynek publikusnak kell lennie (azaz publicnak). NEM BAJ, ha minden függvényünk publikus, csupán több néven kell átlábalnia.

Stock
Ez fordítási időben lényeges. Amennyiben van egy függvényünk (vagy változónk), amit nem használunk, akkor warningot dob rá a fordító. Hibát nem okoz, csupán bennehagytunk vaalmi szemetet.
Amennyiben a függvény/globális változó létrehozásakor stock-ot írunk (globális változó esetén: new helyett stock), akkor a tárgykódba csak akkor fog belefordulni, ha használva is van)

Native
Ennek segítségével teremthetünk kapcsolatot pluginjaink között. Alapesetben a pluginok nem látnak át a másik plugin függvényeibe (de elvileg public-cal deklarált globális változókat látnak, de ezzel nem foglalkozunk. Ki lehet próbálni). Ehhez lehet használni segítségül a native kulcsszót. Ez beregisztrál egy parancsot a magba, aminek meghívásakor a nativehoz rendlet PUBLIKUS függvényt fogja lefuttatni. Ez olyan, mintha magunk írnánk egy saját eseményt, amit egy másik pluginból hívunk.
A függvényt a gazda pluginban kell létrehozni, és ott kell felküldeni a magnak is. A hívó pluginban csupán jelölni kell, hogy létezni fog ilyen függvény. Ezeket szokás elhelyezni az inlcude (inc) állományokba. Természetesen az alap kódba is beírhatjuk, ha az kényelmesebb. (Hiszen tudjuk - ugye - hogy a fordító sem csinál mást)

Példa (full példák, nézzétek meg bátran):

SMA Forráskód: [ Mindet kijelol ]
  1. /////
  2. // GOLLAM.sma
  3. /////
  4. #include <amxmodx>
  5.  
  6. public plugin_init() {
  7. register_plugin("Gollam","1.0","Metal")
  8. }
  9.  
  10. // Natives
  11. public plugin_natives() {
  12. register_native("gollam_valaszol", "native_gollam_valaszol");
  13. }
  14.  
  15. // Natives functions implementations
  16. public native_gollam_valaszol(plugin_id, num_params) {
  17. new id = get_param(1);
  18.  
  19. if (!is_user_connected(id))
  20. {
  21. log_error(AMX_ERR_NATIVE, "[GOLLAM] Invalid Player (%d)", id);
  22. return;
  23. }
  24.  
  25. client_print(id, print_chat, "Nincs nalam a dlagaszak! Elloptak tolunk!!");
  26. }
  27.  
  28. /////
  29. // SZARUMAN.sma
  30. /////
  31. #include <amxmodx>
  32.  
  33. native gollam_valaszol(id);
  34.  
  35. public plugin_init() {
  36. register_plugin("Szaruman","1.0","Metal");
  37. register_clcmd("holagyuru", "HolaGyuru");
  38. }
  39.  
  40. public HolaGyuru(id) {
  41. gollam_valaszol(id);
  42. }
  43.  


Utószó
Kérésem lenne felétek: Akinek van ideje, nyugodtan tesztelje le, s jelezzen vissza, ha valami nem jó. Röpke 1 óra alatt tákoltam össze, tesztelni nem tudtam, de - ha minden igaz -, mindent jól írtam le.
Kérdéseket és a kekszeket várom

Üdv,
Metal

Szerző:  kiki [ 2014.08.19. 13:29 ]
Hozzászólás témája:  Re: AmxModX Alapozó 06. - Függvények

Khm

[ablak]swap(a, b) {
new tmp = a;
a = b;
b = tmp;
}

new a = 10;
new b = 20;
swap(a, b);
log_amx("a: %d, b: %d", a, b); // Eredmény: a: 10, b: 20[/ablak]

fordítva az eredmény :D

Szerző:  Metal [ 2014.08.19. 13:43 ]
Hozzászólás témája:  Re: AmxModX Alapozó 06. - Függvények

Nem, lehetetlen, valamit elnéztél, vagy a referenciásat nézted meg.

kiki írta:
Khm

[ablak]swap(a, b) {
new tmp = a;
a = b;
b = tmp;
}

new a = 10;
new b = 20;
swap(a, b);
log_amx("a: %d, b: %d", a, b); // Eredmény: a: 10, b: 20[/ablak]

fordítva az eredmény :D

Szerző:  Silent [ 2014.08.19. 21:23 ]
Hozzászólás témája:  Re: AmxModX Alapozó 06. - Függvények

Már pedig kikinek van igaza. Ha csak logikusan gondolkozol amit írtál annak nem lenne értelme. Ha "a" 10 volt és "b" 20 volt, valamint a függvény tényleg felcseréli őket, akkor "a" 20 lesz és "b" 10 lesz.

Metal írta:
Nem, lehetetlen, valamit elnéztél, vagy a referenciásat nézted meg.

kiki írta:
Khm

[ablak]swap(a, b) {
new tmp = a;
a = b;
b = tmp;
}

new a = 10;
new b = 20;
swap(a, b);
log_amx("a: %d, b: %d", a, b); // Eredmény: a: 10, b: 20[/ablak]

fordítva az eredmény :D

Szerző:  Metal [ 2014.08.20. 09:17 ]
Hozzászólás témája:  Re: AmxModX Alapozó 06. - Függvények

WRONG... Te se próbáltad ki ... :(

Szerző:  Silent [ 2014.08.20. 10:54 ]
Hozzászólás témája:  Re: AmxModX Alapozó 06. - Függvények

De már te is kijavítottad, miről beszélsz?

Szerző:  Metal [ 2014.08.20. 12:14 ]
Hozzászólás témája:  Re: AmxModX Alapozó 06. - Függvények

Nem értem. Miről mit javítottam?

Szerző:  Silent [ 2014.08.20. 18:22 ]
Hozzászólás témája:  Re: AmxModX Alapozó 06. - Függvények

Metal írta:
Nem értem. Miről mit javítottam?


Kiki idézett egy "WRONG" kódot, ami gondolom eredetileg volt. És már nem az szerepel az eredeti (általad írt) szövegben. Vagy kiki trollkodik? O.o

Szerző:  Metal [ 2014.08.20. 19:29 ]
Hozzászólás témája:  Re: AmxModX Alapozó 06. - Függvények

Nem javítottam semmit, s nem szerkesztettem. 2 példa van, ami az első "hibás", nem azt csinálja, amit kell, viszont a másik meg igen. Le is írtam miért.

Szerző:  Silent [ 2014.08.20. 20:32 ]
Hozzászólás témája:  Re: AmxModX Alapozó 06. - Függvények

Igenigenigen. Félrenéztem. Nem láttam, hogy két kód van, azt hittem, hogy a második kódot írtad az első eredményével (nemtom hogy hoztam össze, ne kérdezd). De valóban most h elolvastam az egészet, tényleg jó. Elnézést kívánok :D

Oldal: 1 / 2 Minden időpont UTC+02:00 időzóna szerinti
Powered by phpBB® Forum Software © phpBB Limited
https://www.phpbb.com/