2016-04-03 7 views
1

Angenommen, ich bin Schnittstelle zu C.Wie kann ich ein externes (C) Funktionsliteral übergeben?

Hier ist eine Umbruchfunktion für die Schnittstelle.

@property extern(C) void onEvent(void function(InterfaceStruct*, int, int, int) nothrow callback) 
{ 
     interfaceSetCallback(handle, callback); 
} 

Alles gut.

wrapper.onEvent = function void (InterfaceStruct*, int x, int y, int z) nothrow 
{ 
     if (x == 11) doSomething(); 
}; 

Uh oh:

Error: function foo.bar.onEvent (void function(InterfaceStruct*, int, int, int) nothrow callback) is not callable using argument types (void function(InterfaceStruct* _param_0, int x, int y, int z) nothrow @nogc @safe) 

So will es mir die Funktionsliteral ist extern haben (C). Wie kann ich das tun? Ich kann keinen Weg finden, dies zu tun.

Antwort

3

Statt die gesamte Funktionsdefinition der Bereitstellung Sie onEvent einfach zuordnen können mit

wrapper.onEvent = (a, x, y, z) 
{ 
    if (x == 11) doSomething(); 
}; 

D wird es automatisch den richtigen Typ zuordnen.

Auch Ihr Code sollte Ihnen tatsächlich einen Syntaxfehler geben, weil extern (C) tatsächlich nicht erlaubt ist, wenn es für eine Funktionszeigerdefinition verwendet wird.

Sie könnten alternativ einen Alias ​​für die Funktion Zeigertyp und werfen die Zuweisung es wie folgt definieren:

alias EventCallback = extern(C) void function(InterfaceStruct*, int, int, int) nothrow; 

@property extern(C) void onEvent(EventCallback callback) 
{ 
     interfaceSetCallback(handle, callback); 
} 

// ... 

wrapper.onEvent = cast(EventCallback) function void(InterfaceStruct*, int x, int y, int z) nothrow 
{ 
     if (x == 11) doSomething(); 
}; 
+0

Hey, danke! Ich konnte online nicht viel über Funktionszeiger oder Literale finden. Danke auch für die zweite Option, die du gegeben hast. Ich kannte das bereits (nachdem ich einen anderen Code angeschaut hatte), aber ich benutze die Casts nicht so oft wie möglich. Glücklicherweise muss ich das jetzt nicht tun. –