2011-12-17

Vala bindings

No man who didn't tried to implement .vapi interface to C-library could fully understand me. I've gone a pretty short path through this hell and already hit so many issues...

Static field construction doesn't even happen for [Compact] classes (bye-bye RAII for library init/cleanup).

[CCode (lower_case_csuffix = "xxx")] - just makes nothing (btw, you can specify any properties and they just would be ignored).

struct don't allow other types declaration inside of it (have no idea what is the reason for that).

string get_driver(); and string dirver { get; } - is totally different things even that C-names for generated code are the same (be careful when uses them in .vapi). First one causes returned string to be freed, but second does nothing (you can try with any type). Nothing special mentioned in documentation.

After narrowing sample and putting it into .vala file you notice that get_dirver() { return "XXX"; } returns g_strdup() of returned value, but dirver { get { /* ... */ } } returns value directly.

To sort that out - you have to use all your charm to squize out of Google several letters in mail-list. 3 years and Google can't find documentation, small wiki page or blog post...

So now we are aware of the fact that default meaning owned/unowned might change depending on context. That makes sense when you want spend minimum effort (not only lines of code, but thinking) to bring another external library to Vala. But that small thing might make harm to your mind. We know that we should write string driver { owned get; } if you want caller to be responsible for removing object.

    [Compact]
    [CCode (cname = "char", free_function = "cpufreq_put_driver")]
    public class Driver : string {
    }

    [SimpleType]
    [Immutable]
    [CCode (cname = "unsigned int", cprefix = "cpufreq_")]
    public struct Cpu : uint {
        public Driver driver { owned get; }
    }
 

But if that would be all problems, I have had, I wouldn't write this post at all...

Simple class similar to one in tutorial:

[SimpleType]
[Immutable]
[CCode (has_type_id = false)]
public struct Cpu : uint {
    public void greet() { stdout.printf("Hi. I'm a 0x%08x\n", this); }
    public double freq {
        get { greet(); return 3.19; }
        set { greet(); }
    }
}

public static void main() {
    Cpu x = 3;
    stdout.printf("freq: %f\n", x.freq);
    x.freq = 4.5;
}
Guess what would be the output?
Hi. I'm a 0x00000003
freq: 3.190000
Hi. I'm a 0xb603a924
If you don't belive me go on and try it at your machine. Maybe you have more luck than I.

Lets see result of vala-0.14 -C property_setter.vala...

void cpu_greet (int32_t self);
gdouble cpu_get_freq (int32_t self);
void cpu_set_freq (int32_t self, gdouble value);
void _vala_main (void);
Nice and clean declarations.

void cpu_greet (int32_t self) {
    FILE* _tmp0_;
    _tmp0_ = stdout;
    fprintf (_tmp0_, "Hi. I'm a 0x%08x\n", (guint) self);
}

gdouble cpu_get_freq (int32_t self) {
    gdouble result;
    cpu_greet (self);
    result = 3.19;
    return result;
}

void cpu_set_freq (int32_t self, gdouble value) {
    cpu_greet (self);
}
Yep, that's what I wanted.

void _vala_main (void) {
    int32_t x;
    FILE* _tmp0_;
    gdouble _tmp1_;
    gdouble _tmp2_;
    x = (int32_t) 3;
    _tmp0_ = stdout;
    _tmp1_ = cpu_get_freq (x);
    _tmp2_ = _tmp1_;
    fprintf (_tmp0_, "freq: %f\n", _tmp2_);
    cpu_set_freq (&x, 4.5);
}
What a hell is that &x doing in my call to setter?.. How did it come to that call of it's own generated function with a wrong type of argument. I've put [SimpleType] as said in tutorial, I've event put [Immutable] to give a hint to Vala. There is no C++ like qualificators for this or at least it's hard to find how to use them other way than by digging into vala code.

I'm giving up on vala...

Update: Found and tickled bug 657346. Hope they will fix.