[Include] Accessing Multi Dimensional PAWN Arrays from C++
#1

I have made a code snippet for anyone making plugins and wanting to access two or three dimensional PAWN arrays.

C++ Header:
pawn Code:
#pragma once
class PawnArray1D
{
private:
    cell * _address;
    size_t _size;
public:
    PawnArray1D(cell * address, size_t size)
    {
        _address = address;
        _size = size;
    }
    PawnArray1D(AMX* amx, cell& param_array, size_t size)
    {
        amx_GetAddr(amx, param_array, &_address);
        _size = size;
    }
    ~PawnArray1D(){}

    size_t GetSize()
    {
        return _size;
    }
    cell &operator()(size_t i)
    {
        return _address[i];
    }
    cell &operator[](size_t index)
    {
        return _address[index];
    }
};

class PawnArray2D
{
private:
    cell * _address;
    size_t _size[2];
public:
    PawnArray2D(cell * address, size_t size_x, size_t size_y)
    {
        _address = address;
        _size[0] = size_x;
        _size[1] = size_y;
    }
    PawnArray2D(AMX* amx, cell& param_array, size_t size_x, size_t size_y)
    {
        amx_GetAddr(amx, param_array, &_address);
        _size[0] = size_x;
        _size[1] = size_y;
    }
    ~PawnArray2D(){}

    size_t GetSize(size_t dimension)
    {
        return _size[dimension];
    }

    cell &operator()(size_t i, size_t j)
    {
        return PawnArray1D((_address + _size[0]) + i*_size[1], _size[1])(j);
        //return *((_address+_size[0])+i*_size[1]+j);
    }
    PawnArray1D &operator[](size_t index)
    {
        return PawnArray1D((_address + _size[0]) + index*_size[1], _size[1]);
    }
};

class PawnArray3D
{
private:
    cell * _address;
    size_t _size[3];
public:
    PawnArray3D(cell * address, size_t size_x, size_t size_y, size_t size_z)
    {
        _address = (cell*)address;
        _size[0] = size_x;
        _size[1] = size_y;
        _size[2] = size_z;
    }
    PawnArray3D(AMX* amx, cell& param_array, size_t size_x, size_t size_y, size_t size_z)
    {
        amx_GetAddr(amx, param_array, &_address);
        _size[0] = size_x;
        _size[1] = size_y;
        _size[2] = size_z;
    }
    ~PawnArray3D(){}

    size_t GetSize(size_t dimension)
    {
        return _size[dimension];
    }
    cell &operator()(size_t i, size_t j, size_t k)
    {
        return PawnArray2D((_address + (_size[0] * _size[1]) + ((_size[1]*_size[2])*i)), _size[0], _size[2])(j, k);
        //return *((_address+_size[0])+i*_size[1]+j);
    }
    PawnArray2D &operator[](size_t index)
    {
        return PawnArray2D((_address + (_size[0] * _size[1]) + ((_size[1] * _size[2])*index)), _size[0], _size[2]);
    }
};
Usage:

C++ code:
pawn Code:
//display contents of arrays and then set the contents to '5' of each element.
static cell AMX_NATIVE_CALL n_TestMultiDimensionalArray1(AMX* amx, cell* params)
{
    printf("TestMultiDimensionalArray1\r\n\tparams[2]-> %d\r\n", params[2]);

    //can be used like this...
    PawnArray1D pawn_array(amx, params[1], params[2]);
    //or...
    for (int i = 0; i < pawn_array.GetSize(); ++i)
    {
        printf("\t\tarray1[%d] -> %08x\r\n", i, pawn_array[i]);
        pawn_array[i] = 5;
    }
    return 1;
}

static cell AMX_NATIVE_CALL n_TestMultiDimensionalArray2(AMX* amx, cell* params)
{
    printf("TestMultiDimensionalArray2\r\n\tparams[2]-> %d\r\n\tparams[3]-> %d\r\n", params[2], params[3]);
   
    //...or can be used like this
    cell *dest = NULL;
    amx_GetAddr(amx, params[1], &dest);
    PawnArray2D pawn_array(dest, params[2], params[3]);

    for (int i = 0; i < pawn_array.GetSize(0); ++i)
    {
        for (int j = 0; j < pawn_array.GetSize(1); ++j)
        {
            printf("\t\tarray2[%d][%d] -> %08x\r\n", i, j, pawn_array[i][j]);
            pawn_array[i][j] = 5;
        }
    }
    return 2;
}

static cell AMX_NATIVE_CALL n_TestMultiDimensionalArray3(AMX* amx, cell* params)
{
    printf("TestMultiDimensionalArray3\r\n\tparams[2]-> %d\r\n\tparams[3]-> %d\r\n\tparams[4]-> %d\r\n", params[2], params[3], params[4]);
   
    cell *dest = NULL;
    amx_GetAddr(amx, params[1], &dest);
    PawnArray3D pawn_array(dest, params[2], params[3], params[4]);

    for (int i = 0; i < pawn_array.GetSize(0); ++i)
    {
        for (int j = 0; j < pawn_array.GetSize(1); ++j)
        {
            for (int k = 0; k < pawn_array.GetSize(2); ++k)
            {
                printf("\t\tarray3[%d][%d][%d] -> %08x\r\n", i, j, k, pawn_array[i][j][k]);
                pawn_array[i][j][k] = 5;
            }
        }
    }
    return 3;
}

AMX_NATIVE_INFO AMXNatives[ ] =
{
    { "TestMultiDimensionalArray1", n_TestMultiDimensionalArray1 },
    { "TestMultiDimensionalArray2", n_TestMultiDimensionalArray2 },
    { "TestMultiDimensionalArray3", n_TestMultiDimensionalArray3 }
};
PAWN Code:
pawn Code:
#include <a_samp>

native TestMultiDimensionalArray1(array[],size=sizeof(array));
native TestMultiDimensionalArray2(array[][],size=sizeof(array),size2=sizeof(array[]));
native TestMultiDimensionalArray3(array[][][],size=sizeof(array),size2=sizeof(array[]),size3=sizeof(array[][]));

#define elem1 (4)
#define elem2 (8)
#define elem3 (2)

main()
{
    new array1[elem1];
    new array2[elem1][elem2];
    new array3[elem1][elem2][elem3];
    for(new i = 0; i < elem1; ++i)
    {
        array1[i] = 0xD1D1A000+(i);
        for(new j = 0; j < elem2; ++j)
        {
            array2[i][j] = 0xE2E2B000+(i<<4)+(j);
            for(new k = 0; k < elem3; ++k)
            {
                array3[i][j][k] = 0xF3F3C000+(i<<8)+(j<<4)+(k);
            }
        }
    }
    for(new i = 0; i < elem1; ++i)
    {
        printf("array1[%d] = %08x -> %d",i,array1[i],array1[i]);
    }
    for(new i = 0; i < elem1; ++i)
    {
        for(new j = 0; j < elem2; ++j)
        {
            printf("array2[%d][%d] = %08x -> %d",i,j,array2[i][j],array2[i][j]);
        }
    }
    for(new i = 0; i < elem1; ++i)
    {
        for(new j = 0; j < elem2; ++j)
        {
            for(new k = 0; k < elem3; ++k)
            {
                printf("array3[%d][%d][%d] = %08x -> %d",i,j,k,array3[i][j][k],array3[i][j][k]);
            }
        }
    }
    TestMultiDimensionalArray1(array1);
    TestMultiDimensionalArray2(array2);
    TestMultiDimensionalArray3(array3);
   
    for(new i = 0; i < elem1; ++i)
    {
        printf("array1[%d] = %08x -> %d",i,array1[i],array1[i]);
    }
    for(new i = 0; i < elem1; ++i)
    {
        for(new j = 0; j < elem2; ++j)
        {
            printf("array2[%d][%d] = %08x -> %d",i,j,array2[i][j],array2[i][j]);
        }
    }
    for(new i = 0; i < elem1; ++i)
    {
        for(new j = 0; j < elem2; ++j)
        {
            for(new k = 0; k < elem3; ++k)
            {
                printf("array3[%d][%d][%d] = %08x -> %d",i,j,k,array3[i][j][k],array3[i][j][k]);
            }
        }
    }
}

public OnGameModeInit()
{
    return 1;
}
See the output yourself!

Works on Windows when compiling with Visual Studio 2013 default compiler (didn't test any other compilers).
Linux version (I did not test the code on linux) may need adjustments (instead adding +x offset to the adress maybe +x*sizeof(cell) is needed).

Edit: Seems to work for enumerated arrays too (even complex ones). (it's just one continous stream of array data)
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)