Search code examples
enumsvalavapi

Declaring a new enum in VAPI binding


I'd like to declare an entirely new enum (instead of binding to C one) in VAPI file. However, when I write

[CCode (has_type_id = false)]
public enum EventKeyState {
    UP = 0,
    DOWN = 1,
    AUTOREPEAT = 2
}

and try to use values, Vala attempts to reference what would be already declared values and promptly errors out on C compiler step:

../tests/test_simple.vala: In function ‘_vala_main’:
../tests/test_simple.vala:7:21: error: ‘EVENT_KEY_STATE_UP’ undeclared (first use in this function)
    7 |         key.state = UP;
      |                     ^~~

How can this be fixed, so Vala will use my new values instead of trying to reference those that aren't declared?


Solution

  • You can group a set of integers in C as a Vala enum by using the CCode attribute. Save the following as example.vapi:

    [CCode (has_type_id = false, cname = "int")]
    public enum EventKeyState {
        [CCode (cname = "0")]
        UP,
        [CCode (cname = "1")]
        DOWN,
        [CCode (cname = "2")]
        AUTOREPEAT 
    }
    
    

    then save the Vala program as main.vala:

    void main () {
        EventKeyState a = DOWN;
    }
    

    Compiling these two with:

    valac example.vapi main.vala --ccode
    

    will generate the main.c file of:

    static void _vala_main (void);
    
    static void
    _vala_main (void)
    {
        int a = 0;
        a = 1;
    }
    
    int
    main (int argc,
          char ** argv)
    {
        _vala_main ();
        return 0;
    }
    

    The C compiler will optimise the initialisation and assignment of a, although there is an argument for the Vala compiler to do this for readability of generated C output.