Welcome, Guest
You have to register before you can post on our site.

Username
  

Password
  





Search Forums



(Advanced Search)

Forum Statistics
» Members: 7,701
» Latest member: zein97174
» Forum threads: 2,356
» Forum posts: 12,303

Full Statistics

Online Users
There are currently 254 online users.
» 0 Member(s) | 251 Guest(s)
Bing, Google, Baidu

Latest Threads
Client issue with object
Forum: Support
Last Post: TheDoctor
2025-11-15, 08:00 PM
» Replies: 0
» Views: 32
San Andreas Police Pursui...
Forum: Advertisements
Last Post: BriBri
2025-11-15, 12:06 AM
» Replies: 0
» Views: 38
[Include] OpenGate (Abrir...
Forum: Portuguese/Portugu?s
Last Post: Crazy_ArKzX
2025-11-13, 06:49 PM
» Replies: 0
» Views: 36
OpenGate (Open Proximity ...
Forum: Libraries
Last Post: Crazy_ArKzX
2025-11-13, 06:46 PM
» Replies: 0
» Views: 40
LS City Hall
Forum: Maps
Last Post: cosminupgaming
2025-11-12, 04:22 PM
» Replies: 3
» Views: 2,661
Crime Base
Forum: Maps
Last Post: cosminupgaming
2025-11-12, 04:19 PM
» Replies: 2
» Views: 1,253
GTA SA-MP Scripting: Issu...
Forum: General Discussions
Last Post: williamrhein
2025-11-12, 10:16 AM
» Replies: 0
» Views: 55
is it worth creating a se...
Forum: General Discussions
Last Post: cosminupgaming
2025-11-11, 05:30 PM
» Replies: 13
» Views: 18,338
Looking for an English De...
Forum: General Discussions
Last Post: cosminupgaming
2025-11-11, 05:21 PM
» Replies: 2
» Views: 2,815
Awakeninga an old server.
Forum: Support
Last Post: drwnrbbt
2025-11-11, 02:26 PM
» Replies: 0
» Views: 57

 
  Returning strings and arrays
Posted by: IllidanS4 - 2019-04-20, 12:07 AM - Forum: Tutorials - Replies (3)

While functions in Pawn typically return only simple cell-sized values, the language does allow for (even native) functions to return arrays and therefore also strings. However, the mechanism that allows it is a bit more complex and may not be suited for some use cases.



First of all, let's look at the standard way of getting a string out of a function.



Via an output parameter

All native SA-MP functions produce a string via a standard non-const array parameter. Since arrays are passed by reference (meaning the function gets access to the actual variable and not just the value inside), the native function can easily store any data inside:

Code:
new name[MAX_PLAYER_NAME  1];

GetPlayerName(playerid, name, sizeof name);

Usually, another parameter is used alongside the array parameter to specify the length of the array. In Pawn, there is no simple way to obtain the length of an array directly at runtime, and so the compiler has to provide the length when needed (the sizeof operator). For strings, an extra cell must be allocated in the array to store the null character, indicating the end of the string (hence the 1).



This way is especially useful for obtaining variable-length arrays (such as strings). The format function, for example, can be only implemented for this way, because the theoretical length of the output string is unlimited.



Returning an array directly

If you want to produce a fixed-size array, you can return it from a function directly:

Code:
forward [MAX_PLAYER_NAME  1]PlayerName(playerid);

stock PlayerName(playerid)

{

??? new name[MAX_PLAYER_NAME  1];

??? GetPlayerName(playerid, name, sizeof name);

??? return name;

}

The forward declaration is optional, but it is useful since it makes you keep in mind that the length of the array is important.



Now, if you know a bit of other languages like C etc., you may be aware that since name is allocated on the stack, it doesn't exist anymore when the function returns. Pawn gets over this fact using a trick ? when the function is called, an extra space for the array is allocated, and the address of this variable is provided to the function via a secret parameter.



In reality, the function looks like this:

Code:
stock PlayerName(playerid, output[MAX_PLAYER_NAME  1])

{

??? new name[MAX_PLAYER_NAME  1];

??? GetPlayerName(playerid, name, sizeof name);

??? output = name;

}

As you can see, returning a string is just a convenient syntactic shortcut for an extra output parameter.



However, this comes at a cost of slightly decreased performance and bugs in certain cases. Let's start with the issues:

Code:
stock Select(index, arg[], arg2[])

{

??? if(index == 0) return arg;

??? return arg2;

}

This simple function seems to return one of the arguments, but since they have indeterminate sizes (represented as 0), the compiler thinks this function returns a zero-sized array and does not actually allocate any extra space for the string. You cannot return strings (or arrays) that have indeterminate length, and the compiler sometimes fails to inform you about this.



Code:
forward [4]Func1();

stock Func1()

{

??? new str[] = "abc";

??? return str;

}



forward [4]Func2();

stock Func2()

{

??? return Func1();

}

This code is also horribly wrong, but in a subtle way. Func2 does allocate extra space for the array returned from Func1, but before the array can be copied to the secret output array of the second function, it is deallocated again and isn't accessible anymore.



Code:
stock Func(...)

{

??? new str[] = "abc";

??? return str;

}

The extra output argument is placed at the end of all arguments, even after the variadic ones. However, the compiler fails to correctly obtain the return address in this case, and assumes its position is constant.



In all these cases, returning a string is a really bad thing to do, since the code usually compiles fine, and the issue only becomes apparent at runtime.



There is a slight performance cost associated with returning arrays as well: the output = name; always happens if the function is implemented in Pawn, and so the array is copied at least once. Take a look at this code:



Code:
new name[MAX_PLAYER_NAME  1]; // = PlayerName(playerid); doesn't work, direct assignment isn't supported

name = PlayerName(playerid);

The compiler again allocates extra space for the string returned from PlayerName (always on the heap), before it moves it to name. Therefore, the array has to be unnecessarily copied twice before it is usable.



As you can see, returning arrays has some significant drawbacks, but it is still useful in some cases, when you are cautious.

Code:
format(string, sizeof string, "Your name is %s.", PlayerName(playerid));

This is the intended usage of returning arrays ? as temporary arguments to other functions. In all other cases, using a normal output parameter is safer and faster. In this case, no extra copying happens at the caller's site.



PlayerName itself can be "fixed" to return the string directly without unnecessary copying, via in-line assembly:

Code:
forward [MAX_PLAYER_NAME  1]PlayerName(playerid);

stock PlayerName(playerid)

{

??? #assert MAX_PLAYER_NAME  1 == 25

??? #emit PUSH.C 25 // size parameter of GetPlayerName

??? #emit PUSH.S 16 // secret return parameter of PlayerName at address 16 (&playerid  4)

??? #emit PUSH.S playerid // equal to 12

??? #emit PUSH.C 12 // number of bytes passed to the function (4 * 3 arguments)

??? #emit SYSREQ.C GetPlayerName // calling the function

??? #emit STACK 16 // cleanup of the arguments from the stack

??? #emit RETN

}

This way, PlayerName does no extra copying, passing the secret return address directly to GetPlayerName.



PawnPlus strings

Dynamic strings in PawnPlus offer the flexibility and convenience of normal values, since they are passed around as references.

Code:
stock String:Func()

{

??? return str_new("abc");

}

The string can be returned from functions, passed to other functions or even to native functions, inspected, or modified, and all of this without any additional copying.



Constant strings

All the previous methods are suitable for strings that are produced at runtime, but for constant strings, I'd advise against using any of them. Use macros instead.



Code:
new const _tips[][] = {

??? "Tip one",

??? "Tip two",

??? "Tip three",

??? "Tip four"

};

#define RandomTip() (_tips[random(sizeof _tips)])

Using this in functions like SendClientMessage requires no string copying at all, since the address of the string is used directly. You can also afford to use variable-length strings in the array, resulting in a little more efficient storage.


  Own logos
Posted by: solstice - 2019-04-19, 11:59 PM - Forum: Art - Replies (1)

removed


  Antiddos Server's
Posted by: air - 2019-04-19, 10:46 PM - Forum: Questions and Suggestions - Replies (1)

Protege a los servidores para que no los ataquen.


  [Showcase] Vice City Roleplay
Posted by: Yazoo - 2019-04-19, 09:33 PM - Forum: Videos and Screenshots - Replies (8)

Here are a few screenshots from when VCRP was being developed before we stopped development due to limitation with the SAMP DL client.



Images:?https://imgur.com/a/1S3zwsF



Fixed/animated custom?escalator:

https://gfycat.com/uncomfortablepracticalkakapo



One member reviewing/testing the server:

https://www.youtube.com/watch?v=VHcYTxkt-DI


  too resource-intensive array
Posted by: Mark2 - 2019-04-19, 08:42 PM - Forum: Pawn Scripting - Replies (5)

I need to create an array(i choosed iterator)?of streamed players for every player. So i got

PHP Code:
Iterator:StreamedPlayers[MAX_PLAYERS]<MAX_PLAYERS

But it's very?resource-intensive, what?can be used instead or may be i don't know something about streaming players?

P.S. I know that i can redefine MAX_PLAYERS to less value but i don't want to do it (1000 default).


  Download fonts and use them in textdraws, chat, more.
Posted by: strcpy - 2019-04-19, 07:27 PM - Forum: Questions and Suggestions - No Replies

You guys should make a browser where i can download any font i wan't and use it to create textdraws, edit chat font (without mods), more.


  Open.MP will have limits?
Posted by: ThePez - 2019-04-19, 06:32 PM - Forum: Questions and Suggestions - Replies (5)

SA-MP is very limited and I don't like it, like NPCs, Vehicles and objects.



https://wiki.sa-mp.com/wiki/Limits



I would like Open.MP to have no limits, or at least to increase the value.


  Geriausi ?aisti ?aidimai?
Posted by: san - 2019-04-19, 06:26 PM - Forum: Lithuanian/Lietuvi?kas - Replies (2)

Hitman Blood money

Max Payne 3

Mafia 2

Garry's Mod

Postal 2

GTA IV


  will be fixed
Posted by: Richard90 - 2019-04-19, 05:24 PM - Forum: General Discussions - Replies (2)

I have questions, Rocket bug will be fixed in open.mp ? Also no reload bug???


  Client-side Scripts
Posted by: Sasino97 - 2019-04-19, 05:20 PM - Forum: Questions and Suggestions - Replies (6)

Client-side Scripts

[Image: zXSrDGv.png]



A feature?that I discussed on Discord.

I think it would be an extremely useful feature, once the?open.mp team starts?working on the client.

This would have a lot of advantages, including optimization by removing the useless?amount of traffic sent between the server and the client, and a better responsiveness.



See the speedometer example in the image above. In a normal SA:MP server, the server is continuously asking the client for his velocity, the client answers, then the server tells the client to redraw the text draw, and so on. This forces the developer to be careful of how often to update the text draw, based on how many players does the server usually have, in order not to slow everything down.



Instead, if the server uploads a (compiled) script to the client upon the first connection, in a similar way to how 0.3DL models are uploaded, and then is able to tell the client when to start and stop its execution, then the speedometer example above can be made in a much more effective ways: the client itself, which knows its own vehicle speed, draws its own text draw as defined by the script, as many times per seconds as the developer wants. This creates a better responsiveness at zero bandwidth cost.