我正在尝试编写一个VAPI文件以在Vala中使用libui (https://github.com/andlabs/libui)。
我不知道如何将来自控件的事件连接到 vala 信号。
在libui headers中,例如关闭窗口,此方法定义了:
_UI_EXTERN void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *w, void *data), void *data);
在 C 示例中,此方法以方法 "onClosesing" 作为参数调用:
uiWindowOnClosing(w, onClosing, NULL);
我怎样才能做出类似的东西:
window.OnClosing.connect(()=>{print("End");});
Vala 中的信号是使用 GLib 的信号实现的,这是观察者模式的一个例子。要在 Vala 中使用信号,该类需要从 Object
继承,看起来libui
并没有使用 GLib 的 GObject。因此,无法在此绑定中使用信号。尽管可以在 Vala 绑定中使用信号。例如,gtksourceview VAPI绑定了SourceBuffer
的redo
和undo
信号。
uiWindowOnClosing
中使用的模式是传递一个 C 函数指针以用作回调。在瓦拉方面,这些被称为代表。 libui
没有为功能点添加 typedef,所以 Vala 需要生成它。这是通过在 VAPI 中使用[CCode (has_typedef = false)]
来指示的。
这里的另一个问题是用户数据的 void 指针 - void *data
。这可能最好使用简单的泛型来绑定。
装订处的粗略切割将是:
[CCode (cname = "uiWindow")]
public class Window {
[CCode (has_typedef = false, simple_generics = true)]
public delegate int Callback<T> (T data);
[CCode (cname = "uiWindowOnClosing", simple_generics = true)]
public void on_closing<K> (Callback callback, K data);
}
这是未经测试的,但应该可以让您更好地了解基本概念。
是不可能的。Vala的signal
机制基于GLib的信号系统。你可以让这些使用 lambda,但不能使用信号。
vapi 中使用您的代码并用这个调用它:
w.on_closing(()=>{Quit();return 0;}, null);
带来以下消息:
error: too many arguments to function ‘uiWindowOnClosing’
uiWindowOnClosing (_tmp3_, ___lambda4__ui_window_callback, NULL, NULL);
但这有效:
public void on_closing (Callback callback);
在 vapi 中,以及
w.on_closing(()=>{Quit();return 0;});
在瓦拉代码中。
谢谢你的帮助。