ccallbackdelegatesvalavapi

How do I specify that user data is provided before the callback parameter in Vala?


I have a C API that looks like this:

typedef void (*cprcen_channel_callback) (CPRC_abuf *abuf, void *user_data);
int CPRCEN_engine_set_callback(CPRCEN_engine *eng, CPRCEN_channel_handle chan,
    void *userdata, cprcen_channel_callback callback);

As you can see, the CPRCEN_engine_set_callback function takes the user data before the callback whereas, by default, Vala expects it to come after. I know about the CCode attribute's delegate_target_pos parameter, but no matter what position I specify, the userdata value gets supplied as the first argument instead of the third in the generated function call. I just can't seem to wrap my head around Vala's parameter positioning logic.

Here's how I'd like the binding to ultimately look:

[CCode(cname = "cprcen_channel_callback", has_target = true)]
public delegate void ChannelCallback(AudioBuffer abuf);

[Compact]
[CCode(cname = "CPRCEN_engine")]
public class Engine {
    [CCode(cname = "CPRCEN_engine_set_callback")]
    public int set_channel_callback(ChannelHandle chan, ChannelCallback callback);
}

How do I make this work?


Solution

  • 1.5 should work:

    [CCode(cname = "CPRCEN_engine_set_callback")]
    public int set_channel_callback(ChannelHandle chan, [CCode (delegate_target_pos = 1.5)] ChannelCallback callback);
    

    The logic is pretty simple. 1.5 is between the first argument (chan) and the second (callback). If you wanted it between the second and third you could use 2.5, and so on.

    Things only really start to get slightly complicated when you want it to precede the instance—in that case you would use something between 0 and 1 (e.g., 0.5) and use the instance_pos CCode attribute to set the instance to something less than 1 but greater than 0.5 (e.g., 0.9).