Difference between revisions of "Talk:Writing Modules In C"
Grazzhoppa (talk | contribs) (Why do you need to declare a Link* named ink when using FOR_EACH_PLAYER macro?) |
(→Bug?) |
||
(3 intermediate revisions by 2 users not shown) | |||
Line 5: | Line 5: | ||
quote from article: | quote from article: | ||
"''There is an ASSS macro, FOR_EACH_PLAYER, that will help us loop through every player. To use this macro we need: a Player* '''and a Link* named link.'''''" | "''There is an ASSS macro, FOR_EACH_PLAYER, that will help us loop through every player. To use this macro we need: a Player* '''and a Link* named link.'''''" | ||
+ | |||
+ | [[User:Mine GO BOOM|Mine GO BOOM]] 15:56, Oct 3, 2006 (PDT): In player.h, the macro FOR_EACH_PLAYER is defined as the following. The for line assumes a '''Link*''' variable named '''link''' for it to work correctly. Under C++, you could initalize the '''link''' variable in the '''for''' loop but you cannot in C. A slightly better method would have the '''Link*''' variable name be include in the macro's definition instead of assuming a variable named '''link'''. | ||
+ | <pre>#define FOR_EACH_PLAYER(p) \ | ||
+ | for ( \ | ||
+ | link = LLGetHead(&pd->playerlist); \ | ||
+ | link && ((p = link->data, link = link->next) || 1); )</pre> | ||
+ | |||
+ | |||
+ | === Bug? === | ||
+ | |||
+ | So looking back on this tutorial I think | ||
+ | <pre> | ||
+ | if (action == MM_LOAD) | ||
+ | { | ||
+ | mm = mm_; | ||
+ | |||
+ | chat = mm->GetInterface(I_CHAT,ALLARENAS); | ||
+ | aman = mm->GetInterface(I_ARENAMAN, ALLARENAS); | ||
+ | pd = mm->GetInterface(I_PLAYERDATA,ALLARENAS); | ||
+ | |||
+ | if (!chat || !aman || !pd) // check interfaces | ||
+ | rv = MM_FAIL; | ||
+ | else | ||
+ | { | ||
+ | // allocate data | ||
+ | arenaKey = aman->AllocateArenaData(sizeof(MyArenaData)); | ||
+ | playerKey = pd->AllocatePlayerData(sizeof(MyPlayerData)); | ||
+ | |||
+ | if (!arenaKey || !playerKey) // check if we ran out of memory | ||
+ | { | ||
+ | rv = MM_FAIL; | ||
+ | } | ||
+ | else | ||
+ | { // declare callbacks, commands, and timers | ||
+ | mm->RegCallback(CB_SHIPCHANGE, ShipChange, ALLARENAS); | ||
+ | rv = MM_OK; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | fails to release the interfaces when there's an error, which will create problems when modules unload. After "rv = MM_FAIL;", in both instances, I think it's necessary to add | ||
+ | <pre> | ||
+ | mm->releaseInterface(chat); | ||
+ | mm->releaseInterface(aman); | ||
+ | mm->releaseInterface(pd); | ||
+ | </pre> | ||
+ | |||
+ | also, the modules shouldn't be listening for MM_ATTACH AND MM_DETACH if it's never using those guys (or the tutorial should cover what they do). | ||
+ | |||
+ | Let me know if I'm wrong. [[User:BaK|BaK]] | ||
+ | |||
+ | Yes the interfaces and allocated arena/player data should be freed properly. However since modules are usually loaded at startup if any module fails to load the server will exit, so any leaks would not matter. [[User:Smong|Smong]] 08:05, Apr 8, 2007 (PDT) |
Latest revision as of 10:05, 8 April 2007
The example given for how to use the FOR_EACH_PLAYER macro doesn't show why you need a Link pointer named link!
The example just declares the variable, without initializing it to any value, and doesn't do anything with the Link pointer after that.
quote from article: "There is an ASSS macro, FOR_EACH_PLAYER, that will help us loop through every player. To use this macro we need: a Player* and a Link* named link."
Mine GO BOOM 15:56, Oct 3, 2006 (PDT): In player.h, the macro FOR_EACH_PLAYER is defined as the following. The for line assumes a Link* variable named link for it to work correctly. Under C++, you could initalize the link variable in the for loop but you cannot in C. A slightly better method would have the Link* variable name be include in the macro's definition instead of assuming a variable named link.
#define FOR_EACH_PLAYER(p) \ for ( \ link = LLGetHead(&pd->playerlist); \ link && ((p = link->data, link = link->next) || 1); )
Bug?
So looking back on this tutorial I think
if (action == MM_LOAD) { mm = mm_; chat = mm->GetInterface(I_CHAT,ALLARENAS); aman = mm->GetInterface(I_ARENAMAN, ALLARENAS); pd = mm->GetInterface(I_PLAYERDATA,ALLARENAS); if (!chat || !aman || !pd) // check interfaces rv = MM_FAIL; else { // allocate data arenaKey = aman->AllocateArenaData(sizeof(MyArenaData)); playerKey = pd->AllocatePlayerData(sizeof(MyPlayerData)); if (!arenaKey || !playerKey) // check if we ran out of memory { rv = MM_FAIL; } else { // declare callbacks, commands, and timers mm->RegCallback(CB_SHIPCHANGE, ShipChange, ALLARENAS); rv = MM_OK; } } }
fails to release the interfaces when there's an error, which will create problems when modules unload. After "rv = MM_FAIL;", in both instances, I think it's necessary to add
mm->releaseInterface(chat); mm->releaseInterface(aman); mm->releaseInterface(pd);
also, the modules shouldn't be listening for MM_ATTACH AND MM_DETACH if it's never using those guys (or the tutorial should cover what they do).
Let me know if I'm wrong. BaK
Yes the interfaces and allocated arena/player data should be freed properly. However since modules are usually loaded at startup if any module fails to load the server will exit, so any leaks would not matter. Smong 08:05, Apr 8, 2007 (PDT)