Raised This Month: $51 Target: $400
 12% 

Dynamically sized arrays in Pawn


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
klippy
AlliedModders Donor
Join Date: May 2013
Location: Serbia
Old 06-20-2015 , 11:54   Dynamically sized arrays in Pawn
Reply With Quote #1

Before you start bashing me how useless this is - I created this because I like playing with Pawn assembly and its underlying structure. I had fun writing this, and I wanted to share my results with you. It's also one of the key features I miss in Pawn. Also, I'm not saying you should include this in your plugins, and you probably shouldn't! It most probably won't make your plugin more efficient! You should use this only if you would like to experiment with it.
_______________________

This is one of the features in SourcePawn that I've wanted in AMXX(Pawn) for a long time - arrays with indeterminate size.
In AMXX, arrays have to have their size determined at compile-time. In SourcePawn, arrays can have their size determined at run-time too, which is why they are called "dynamic" - their size can change, it's not hardcoded.
I've got the idea from SA-MP forums, and also learned something new I used in my code. THIS is the thread I got the main idea from, they implemented pointers in Pawn. Slice helped me a lot by publishing that little library.
This is purely written in Pawn, no native calls are used.

Scroll down if you are not interested in how this exactly works.

This works by exploiting an interesting bug (or a feature?) in the compiler that let's you write such code:
Code:
new myarray[64];
(((myarray[2])[4])[6])[8] = 1337;
// Which is equal to:
myarray[2 + 4 + 6 + 8] = 1337;
It also works by patching some memory at run-time. 2D and 3D arrays in Pawn have headers to them, at the start of memory block they allocate. The header contains offset to each entry in the array. Meaning that such array:
PHP Code:
new myarray[][] =
{
    
"Hello",
    
"World"
}; 
translates to this in memory (each value listed is 1 CELL in size, not 1 BYTE):
Code:
8, 28, 'H', 'e', 'l', 'l', 'o', '\0', 'W', 'o', 'r', 'l', 'd', '\0'
By changing that header at run-time, I get the effect of my array changing its location in memory.

These arrays work pretty much like C/++ dynamically allocated arrays - you get a pointer which points to a block of memory that's been allocated. This means that a single array (probably? not tested yet) can have more than 3 dimensions. You can achieve that by having an array of pointers, each pointing to another array of pointers, where each pointer points to another array of pointers, each pointing to... Oh Gosh...
You could also make a pointer point to another variable (C/++ behaviour), by using ref<variable> to get its address. I have no idea what it would be useful for, but it's there just in case.
_______________________

What can this be useful for?
Here's an example: you want to read a whole file into a single array. By using the old method with statically sized arrays, most of the times you would end up either having a lot of unused memory if your file is too small, or worse, not having enough memory allocated, ending up in data loss.
By calling file_size() function, you get to know exactly how much memory you need to allocate to read your file!

Usage
To allocate memory, use:
PHP Code:
// !There must be no whitespaces between "new" and the opening square bracket! //
new myarray = new[1337]; 
To access memory, use:
PHP Code:
// Yes, you need both underscore and a dollar sign. It may look ugly, but macros are really limited. Tried to make it as beautiful as possible
_$myarray[index]

_$myarray[69] = 1337;

// Yes, you need that "[0]" even if you are passing the array itself! That's another limitation
copy(_$myarray[0], 69"KliPPy Owns \o/");

// This will actually set 3rd index in myarray[]. You can do pointer arithmetic, just like in C/++.
// Also, it's 3rd index because it's calculated in bytes, and not cells. This means that it should be multiplied by 4 (3 * 4 = 12)
_$(myarray 12)[0] = 1337
EDIT:
Memory also had to be freed before. KORD pointed out that the heap pointer resets every time AMX calls a public function within the plugin. That means that there's actually no need to free memory, as it is automatically done!

This was mostly done to prove that dynamic arrays can be implemented in Pawn using its current instruction set. That means that only the compiler has to be modified to make this work, also meaning this should work on older AMXX versions too. I'm hoping to see this implemented in Pawn one day.

Also, thanks to Backup for giving me some ideas and keeping me entertained while writing this.

P.S. Look at the .inc file for more information. It's also well commented, explaining what exactly is going on.
Attached Files
File Type: inc dynarrays.inc (2.8 KB, 469 views)

Last edited by klippy; 06-21-2015 at 04:55. Reason: Update
klippy is offline
KORD_12.7
Senior Member
Join Date: Aug 2009
Location: Russia, Vladivostok
Old 06-20-2015 , 12:26   Re: Dynamically sized arrays in Pawn
Reply With Quote #2

Good job.

Upd:
Not sure that your code will work properly:
PHP Code:
#emit SCTRL 2 // Allocate memory by moving the heap pointer 
AMXX will restore original value for heap in next "frame", look amx_Exec in AMXX src.
__________________

Vi Veri Veniversum Vivus Vici
Russian Half-Life and Adrenaline Gamer community

Last edited by KORD_12.7; 06-20-2015 at 12:47.
KORD_12.7 is offline
Send a message via ICQ to KORD_12.7
KORD_12.7
Senior Member
Join Date: Aug 2009
Location: Russia, Vladivostok
Old 06-20-2015 , 12:46   Re: Dynamically sized arrays in Pawn
Reply With Quote #3

Here is simple code to check this:
PHP Code:
#include <amxmodx>

public plugin_init()
{
    new 
HEA;
    
    
#emit LCTRL 2
    #emit STOR.S.pri HEA
    
    
server_print(" * HEA before alloc: %d"HEA);
    
    
#emit LCTRL 2
    #emit ADD.C 48
    #emit SCTRL 2
    #emit STOR.S.pri HEA
    
    
server_print(" * HEA after alloc: %d"HEA);
}

public 
plugin_cfg()
{
    new 
HEA;
    
    
#emit LCTRL 2
    #emit STOR.S.pri HEA
    
    
server_print(" * HEA restored by AMXX: %d"HEA);

__________________

Vi Veri Veniversum Vivus Vici
Russian Half-Life and Adrenaline Gamer community
KORD_12.7 is offline
Send a message via ICQ to KORD_12.7
klippy
AlliedModders Donor
Join Date: May 2013
Location: Serbia
Old 06-20-2015 , 13:04   Re: Dynamically sized arrays in Pawn
Reply With Quote #4



I totally overlooked that, but that information actually helps me!

amx_Exec() function is used to call a public function within a plugin, given its index from the public functions table. It resets every time it calls A PUBLIC function, not if I call a function from my plugin (or the next "frame"). That means that there's no need for delete[] function, AMX will free memory on its own!
Thanks for pointing that out, will update the file in a minute.

EDIT: Updated. There's no need to free memory anymore.

Last edited by klippy; 06-20-2015 at 13:12.
klippy is offline
Destro-
Veteran Member
Join Date: Jun 2010
Location: $me->location();
Old 06-20-2015 , 14:29   Re: Dynamically sized arrays in Pawn
Reply With Quote #5

awesome :O
__________________
Destro- is offline
milutinke
AlliedModders Donor
Join Date: Jun 2012
Location: Serbia
Old 06-20-2015 , 17:24   Re: Dynamically sized arrays in Pawn
Reply With Quote #6

Interesting
milutinke is offline
Send a message via Skype™ to milutinke
georgik57
Veteran Member
Join Date: Oct 2008
Location: 🎧Music World
Old 06-21-2015 , 04:13   Re: Dynamically sized arrays in Pawn
Reply With Quote #7

Good job.
__________________
georgik57 is offline
Send a message via MSN to georgik57 Send a message via Yahoo to georgik57 Send a message via Skype™ to georgik57
klippy
AlliedModders Donor
Join Date: May 2013
Location: Serbia
Old 06-21-2015 , 04:40   Re: Dynamically sized arrays in Pawn
Reply With Quote #8

Thanks guys.

Last edited by klippy; 06-21-2015 at 04:40.
klippy is offline
meTaLiCroSS
Gaze Upon My Hat
Join Date: Feb 2009
Location: Viņa del Mar, Chile
Old 06-21-2015 , 04:49   Re: Dynamically sized arrays in Pawn
Reply With Quote #9

What is _DA@ ? D:
__________________
Quote:
Originally Posted by joropito View Post
You're right Metalicross
meTaLiCroSS is offline
klippy
AlliedModders Donor
Join Date: May 2013
Location: Serbia
Old 06-21-2015 , 04:51   Re: Dynamically sized arrays in Pawn
Reply With Quote #10

Quote:
Originally Posted by meTaLiCroSS View Post
What is _DA@ ? D:
Nothing really, just a part of variable/function name. Used that not to fill up the global scope, as I am sure no one will use similar symbol names to these. DA stands for "Dynamic Array".

EDIT:
Updated, removed some unneeded comments from the include file.

Last edited by klippy; 06-21-2015 at 04:56.
klippy is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 18:41.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode