8.4. Function Pointers

Fields that are function pointers have more complexity depending on ownership and targeting. If a delegate is targetless then it can be treated as a simple type and no ownership considerations are needed.

If a delegate has a target then the C structure must have an holder for the target:

typedef void(*foo_func)(int a, void *userdata);

typedef struct {
    foo_func callback;
    void *callback_context;
} foo;
[CCode (cname = "foo_func")]
public delegate void FooFunc(int a);

public struct Foo {
    [CCode (delegate_target_cname = "callback_context")]
    public unowned FooFunc callback;
}

Check for nullability as per usual.

Ownership is slightly more complex as there must be a field to hold a function that will free the context data. In GLib terminology, this is a destroy notification.

typedef void(*foo_func)(int a, void *userdata);

typedef struct {
    foo_func callback;
    void *callback_context;
    void(*callback_free)(void*);
} foo;
[CCode (cname = "foo_func")]
public delegate void FooFunc(int a);

public struct Foo {
    [CCode (delegate_target_cname = "callback_context", delegate_target_destroy_notify_cname = "callback_free")]
    public FooFunc callback;
}

If the function pointer will be called exactly once and calling it should result in destruction of the context then use scope = "async".

typedef void(*start_job)(int priority, void *context);

void threadpool_queue_job(Pool *p, start_job j, void *context);
[CCode (scope = "async", cname = "start_job")]
public delegate void StartJob (int priority);

public class ThreadPool {
    public void queue_job (StartJob j);
}