vala - 没有实例方法或闭包的目标无法创建委托(delegate)是什么意思

标签 vala

我正在使用瓦拉。
这是给出编译时错误的源代码:

private Gee.HashMap<string,VoidFunc> fill_actions()
{
    var actions = new Gee.HashMap<string,VoidFunc>();
    MainWindow win = window;
    actions["t"] = () => _puts(win.title);
    return actions;
}

首先,我尝试直接访问 this.window ,但这给出了另一个错误,所以我使用本地范围变量进行了尝试。

直接执行 this.window 时出错:
This access invalid outside of instance methods

最佳答案

听起来 VoidFunc 是用 [CCode (has_target = false)] 声明的。这意味着没有上下文信息传递给它,而 AFAIK 是委托(delegate)作为泛型类型参数工作的唯一方式。这样做的原因是 C 语言的限制,所以假设 VoidFunc 看起来像这样:

[CCode (has_target = false)]
public delegate void VoidFunc ();

你会在 C 中得到的东西是这样的:
typedef void (*VoidFunc)();

如果您没有 [CCode (has_target = false)],则与类似的情况相反:
typedef void (*VoidFunc)(gpointer user_data);

当您在 C 中传递回调时,通常会使用一到三个参数。所有这三个的东西看起来像这样:
void foo (VoidFunc void_func, gpointer user_data, GDestroyNotify notify);

第一个参数是实际功能。第二个参数是作为 user_data 传递给回调的值,它是 Vala 用来将上下文信息传递给回调的值(这允许它充当实例方法,甚至是闭包)。第三个参数用于指定在不再需要时释放 user_data 的函数。

[CCode (has_target = false)] 的意思是委托(delegate)没有 user_data 参数,因此不能用作闭包或实例方法。

这对于泛型参数来说是必要的原因是泛型在 C 级别看起来像这样:
void foo_bar (gpointer data, GDestroyNotify notify);

第一个参数是您要用作通用值的数据,第二个参数实际上只有在拥有通用参数时才添加(就像在 Gee 中的 set 方法的情况下一样),并使用 user_data 作为不再需要 user_data 时的参数。

如您所见,当尝试将委托(delegate)用作泛型时,没有地方可以放置 user_data 参数,这就是为什么 Vala 只允许没有目标的委托(delegate)作为泛型参数。

解决方案基本上是将委托(delegate)包装在一个类中:
public delegate void VoidFunc ();

public class YourClass {
  private class VoidFuncData {
    public VoidFunc func;

    public VoidFuncData (owned VoidFunc func) {
      this.func = (owned) func;
    }
  }

  private Gee.HashMap<string,VoidFuncData> fill_actions() {
    var actions = new Gee.HashMap<string,VoidFuncData>();
    string win = "win";
    actions["t"] = new VoidFuncData (() => GLib.debug (win));
    return actions;
  }
}

关于vala - 没有实例方法或闭包的目标无法创建委托(delegate)是什么意思,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11314163/

相关文章:

ubuntu - 在 pkg-config 搜索路径中找不到构建验证 : Package libvala-0. 12

vala - 如何从 Vala 中的字符串创建输入流

css - GtkStyleProvider - 提供自己的实现

Vala const 从读写变量初始化

linux - GLib.Settings.changed 事件未触发

c++ - E.CalView 在 Vala 中的使用

c++ - 我有机会用 Vala 和 C++ 保持类型安全和内存抽象吗?

ssl - 如何在 libsoup 中使用 HTTPS 接受所有证书(甚至无效)?

introspection - Vala VAPI 和 GObject Introspection 之间有什么关系?

webkit/webkit.h : No such file or directory