Search code examples
c-preprocessord

Translating C preprocessor macro to a D template or mixin


I'm working on translating a C library to D and I was wondering what the best way to mimic the following C preprocessor macro in D is.

#define LV2_ATOM_SEQUENCE_FOREACH(seq, iter) \
for (LV2_Atom_Event* (iter) = lv2_atom_sequence_begin(&(seq).body); \
    !lv2_atom_sequence_is_end(&(seq).body, (seq).atom.size, (iter)); \
    (iter) = lv2_atom_sequence_next(iter))

Is this even possible to mimic with template programming or mixins in D?

An example of how the macro is used is

LV2_ATOM_SEQUENCE_FOREACH(self->control, event) {
    do stuff with 'event'
    ...
}

I've tried writing a template which does something similar but I havent had much luck.

Any help or suggestions would be appreciated.


Solution

  • After a lot of trial and error I got it to work.

    void LV2_ATOM_OBJECT_FOREACH(const (LV2_Atom_Object*) obj, void delegate(LV2_Atom_Property_Body* prop) iterDelegate) 
    {
        for (LV2_Atom_Property_Body* iter = lv2_atom_object_begin(&obj.body);
            !lv2_atom_object_is_end(&obj.body, obj.atom.size, iter);
            iter = lv2_atom_object_next(iter))
        {
            iterDelegate(iter);
        }
    }
    

    Then where the function is used

    LV2_ATOM_OBJECT_FOREACH(object, delegate(LV2_Atom_Property_Body* prop)
    {
        ...use prop here...
    });
    

    I'm still not sure that this is completely correct. The calling function is extern(C) If i try to make LV2_ATOM_OBJECT_FOREACH extern(C) as well I get the following error

    function dplug.lv2.atomutil.LV2_ATOM_OBJECT_FOREACH(const(LV2_Atom_Object*) obj, extern (C) void delegate(LV2_Atom_Property_Body* prop) iterDelegate) is not callable using argument types (const(LV2_Atom_Object*), void delegate(LV2_Atom_Property_Body* prop) nothrow @system)

    Thanks a lot to Adam for the suggestions on how to approach this problem.