[Include] variadic.inc - Variadic functions in PAWN
#1

Variadic functions in PAWN


Introduction

Variadic functions are a feature in most scripting languages, where a scripter can specify an indefinite amount of arguments towards a function. However, in PAWN, this isn't possible without playing around with the assembly (later versions of PAWN have dealt with this), but this include introduces a brand new way of handling them!

The include was originally created by Emmet_ and is now maintained by me. Most of the credits for the include still go to Emmet_, I have only added support for mysql_format and done a few other changes.


More information

Have you ever wrote a function like this before?

PHP код:
printex(str[], ...)
{
    new 
output[128];
    
format(outputsizeof(output), str, ...);
    
    return print(
output);

And then you figured out that you can't do it this way! The reason being is because variadic parameters don't have a referable location in ordinary PAWN code, so assembly is required, but that can be very complicated and one mistake could corrupt the entire script.

However, this include allows scripters to dynamically push arguments and format them. The pushed arguments are stored within an array by address, so they can be accessed later with the corresponding functions.


Example

An equivalent of the function in the introduction is possible using this include:

PHP код:
#include <a_samp>
#include <variadic>
var printex(str[])
{
    new 
output[128];
    
format(outputsizeof(output), str, @variadic[1]);
    
    return print(
output);

You can also use @variadic[] with CallLocalFunction and such to call local functions with the corresponding pushed arguments.

Alternatively, you can also use another keyword (or none) instead of var, but make sure you place ... after the parameters.


String arguments

You can retrieve string arguments easily.


Getting:

PHP код:
MyFunction(a[], b[])
{
    new 
addr GetVariadicAddress(0); // Address of "a[]".
    
print(GetVariadicString(addr)); // Print the result.

Setting:

PHP код:
MyFunction(a[], b[])
{
    new 
addr GetVariadicAddress(1); // Address of "b[]".
    
SetVariadicString(addr"Hi there.");
    print(
GetVariadicString(addr)); // Print the result.

Functions

PHP код:
// Get the address of a function argument.
native GetVariadicAddress(argument);
// Get the string from the specified argument address. You can return it or store it inside "dest".
native GetVariadicString(addressdest[] = ""size sizeof(dest));
// Set the string from the specified argument address to the specified string.
native SetVariadicString(addressstr[]);
// Checks if an argument is packed.
native IsArgumentPacked(address);
// Gets the length of a variadic string.
native GetVariadicLength(address);
// Delete an argument from the specified argument address.
native DeleteArgument(address);
// Popped the pushed arguments.
native PopArguments(); 
Installation

Simply install to your project:

Код:
sampctl package install kristoisberg/variadic
Include in your code and begin using the library:

PHP код:
#include <variadic> 
Credits
  • Emmet_ - The original creator of the include, an absolute legend.
  • kvann - Current maintainer.
  • Southclaws - Added sampctl support, some minor changes.

Download

https://github.com/kristoisberg/variadic
Reply
#2

Are there any differences between this include and y_va?
Reply
#3

Quote:
Originally Posted by ExTaZZ69
Посмотреть сообщение
Are there any differences between this include and y_va?
They generally have the same purpose and mostly offer the same possibilities. Emmet_ said in his original thread that y_va should be the preferred option, but in case you want to keep your scripts YSI-free like many scripters (including me) do these days, then I can guarantee you that this include is completely stable. I've been using it since it originally came out (december 2013) and I've had no issues with it at all.
Reply
#4

Quote:
Originally Posted by kvann
Посмотреть сообщение
They generally have the same purpose and mostly offer the same possibilities. Emmet_ said in his original thread that y_va should be the preferred option, but in case you want to keep your scripts YSI-free like many scripters (including me) do these days, then I can guarantee you that this include is completely stable. I've been using it since it originally came out (december 2013) and I've had no issues with it at all.
y_va can be easily YSI free. For example I use y_va without YSI in my zlang lib. Look at here: https://github.com/Open-GTO/zlang/blob/master/zlang.inc
Reply
#5

Sorry for butting in but why YSI free?
Reply
#6

Quote:
Originally Posted by RogueDrifter
Посмотреть сообщение
Sorry for butting in but why YSI free?
when you compile with the YSI libary it adds on a few seconds to the compile time

i'm sure there may be a better reason i do not know
Reply
#7

Quote:
Originally Posted by rfr
Посмотреть сообщение
when you compile with the YSI libary it adds on a few seconds to the compile time

i'm sure there may be a better reason i do not know
In the most cases people don't use the whole YSI power. It's like an overkill i guess. If i'm wrong i hope someone will correct me.
Reply
#8

Hello,
I want to do something like the following:
pawn Код:
stock Event_Fire(Event: event, const fmt[], {Float, _}:...)
{
    for (new i = 0; i < callbackCount[event]; i++)
    {
        CallLocalFunction(callbacks[event][i], fmt, /* the rest of the params */);
    }
}
Is this library appropriate to solve this problem, or is it better to use y_va?
Reply
#9

Quote:
Originally Posted by Sasino97
Посмотреть сообщение
Hello,
I want to do something like the following:
pawn Код:
stock Event_Fire(Event: event, const fmt[], {Float, _}:...)
{
    for (new i = 0; i < callbackCount[event]; i++)
    {
        CallLocalFunction(callbacks[event][i], fmt, /* the rest of the params */);
    }
}
I haven't taken a look at this include in months since my stance on YSI has changed drastically ever since ****** joined SA-MP Discord. I would definitely recommend you to use y_va, but this this include can also do it if you put @variadic[2] in the place of the comment.
Reply


Forum Jump:


Users browsing this thread: 3 Guest(s)