Search code examples
pythoncstructswig

How to initialize C struct members at creation in SWIG for Python?


Let's say we have a following struct in C:

typedef struct buffer
{
    uint8_t* const data;
    const size_t maxSize;
    size_t size;
} buffer_t;

How can I make a SWIG wrapper for this so that when buffer_t is created in Python it allocates given number of bytes to data pointer and sets maxSize accordingly?

Details

So basically the problem here is related to constant struct members. By default SWIG initializes structs with default values. This leads into problems:

StructWithConsts_t struct;
struct.constant = 5; // Error. This should've been set when creating the struct.

The accepted answer with constructors and destructors provide solution for this problem.


Solution

  • You can treat C structs as C++ classes in SWIG and extend them with creators and destroyers methods.

    In your case your .i should have this

    typedef struct
    {
        uint8_t* const data;
        const size_t maxSize;
        size_t size;
    } buffer_t;
    
    %extend buffer_t {
        buffer_t(size_t size)
        {
            buffer_t* pBuffer = malloc(sizeof *pBuffer);
            pBuffer->data = malloc(size * sizeof (*pBuffer->data));
            pBuffer->maxSize = size;
            return pBuffer;
        }
    
        void ~buffer_t()
        {
            buffer_t *pBuffer = ($self);
            free(pBuffer->data);
            free(pBuffer);
            return;
        }
    };
    

    In python it will be used like this

    from yourmodule import buffer_t
    
    buffer = buffer_t(10)
    

    The garbage collector will take care of freeing the memory.

    There are other ways of doing this but you don't have a reproducing example to test it out.