Introduction

The framework has plenty of options to interact with native functions. Natives can either be called via static delegate fields (which is much the easiest way of doing it) or via a Native.Load/INative.Invoke call.

Notice! Most of the natives provided by SA-MP are available via the classes available within the framework. Some natives (mostly the math related ones) are not implemented because it is much easier to use the comparable methods provided by the .NET framework. If you still come across a not implemented native, send an issue.

Loading a Native

You can load a native by calling Native.Load and specifying the name and parameter types of the function. If the native exists Native.Load returns an instance of type INative, otherwise null is returned. A native can be invoked by calling Native.Invoke. As parameters you can specify an array of arguments. Because the args parameter is marked with the params keyword, you can simply input multiple arguments, as shown in the SendClientMessageToAll below.

// native SendClientMessageToAll(color, const message[]);
var native = Native.Load("SendClientMessageToAll", typeof(int), typeof(string));

native.Invoke(0xffffffff, "An exemplary message.");

If an argument if of a output type, you can simply pass null in the arguments array. The value will be set after the INative.Invoke is called.

// native GetPlayerName(playerid, const name[], len);
var native= Native.Load("GetPlayerName", typeof(int), typeof(string).MakeByRefType(), typeof(int));

var args = new object[] {0, null, 32};
native.Invoke(args);
var name = args[1] as string;

Console.WriteLine("Name: {0}", name);

Existence Check

To check if a native exists, simply call Native.Exists with the name of the native. This can for example be used to check if a certain plugin is loaded.

if(!Native.exists("Streamer_Update"))
{
    Console.WriteLine("Streamer was not loaded!");
}

Length Specifiers

If a native has an output argument of type string, int[], float[] or bool[] or an input argument of type int[], float[] or bool[] the framework needs to know at which parameter index the length of the argument is specified. If you don't specify these indices, the framework will assume the size is specified in the next parameter.

// native SomeNative(indices[], Float:points[], indicesCount, pointsCount);
Native.Load("SomeNative", new[] {2, 3}, new Type[] typeof(int[]), typeof(float[]), typeof(int));