C语言中创建GListStore时,构造函数第一个参数的正确GType该如何指定?
C语言中创建GListStore时,构造函数第一个参数的正确GType该如何指定?
嘿,我来帮你理清这个问题!你遇到的断言错误其实是踩了GListStore的核心规则——它只能用来存储GObject子类的实例,普通的字符串(gchar*)或者指针类型根本不符合要求,所以用G_TYPE_POINTER才会触发那个g_type_is_a (item_type, G_TYPE_OBJECT)的断言失败。
那具体该传什么GType呢?分两种情况看:
情况1:你要存储的是GObject子类的实例
如果你的列表是用来放GTK控件(比如按钮、标签)或者自定义的GObject对象,直接传对应类的GType就行。比如要存按钮,就传GTK_TYPE_BUTTON;要存你自己定义的MyCustomObject类,就传MY_TYPE_CUSTOM_OBJECT。
情况2:你要存储字符串这类非GObject类型
这时候不能直接存原始字符串,得用GObject的包装类型,有两个简单的方案:
方案1:用GTK提供的字符串包装类(推荐,GTK 4.6+可用)
GTK 4.6之后专门提供了GtkStringObject,它就是用来把普通字符串包装成GObject的工具类,对应的GType是GTK_TYPE_STRING_OBJECT。用它的话代码会很简洁:
// 创建GListStore GListStore *store = g_list_store_new(GTK_TYPE_STRING_OBJECT); // 把字符串包装成GtkStringObject再添加 const gchar *my_str = "Hello GListStore"; GtkStringObject *str_obj = gtk_string_object_new(my_str); g_list_store_append(store, str_obj); // 注意:GListStore会自动持有元素的引用,所以这里可以unref释放我们手上的引用 g_object_unref(str_obj); // 从列表里读取字符串的示例 GtkStringObject *retrieved_obj = g_list_model_get_item(G_LIST_MODEL(store), 0); const gchar *retrieved_str = gtk_string_object_get_string(retrieved_obj); printf("取到的字符串:%s\n", retrieved_str); g_object_unref(retrieved_obj);
方案2:自己定义一个简单的GObject子类封装字符串
如果你的GTK版本低于4.6,或者需要自定义更多逻辑,可以自己写一个极简的GObject子类来存字符串:
// 先定义我们的字符串持有类 #define TYPE_STRING_HOLDER (string_holder_get_type()) G_DECLARE_FINAL_TYPE(StringHolder, string_holder, STRING_HOLDER, GObject) struct _StringHolder { GObject parent_instance; gchar *str; // 用来存字符串的属性 }; // 实现GObject的必要宏和方法 G_DEFINE_TYPE(StringHolder, string_holder, G_TYPE_OBJECT) // 析构函数,负责释放字符串内存 static void string_holder_dispose(GObject *object) { StringHolder *self = STRING_HOLDER(object); g_free(self->str); // 别忘了调用父类的析构逻辑 G_OBJECT_CLASS(string_holder_parent_class)->dispose(object); } static void string_holder_class_init(StringHolderClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); object_class->dispose = string_holder_dispose; } static void string_holder_init(StringHolder *self) { self->str = NULL; } // 封装一个创建实例的便捷函数 StringHolder *string_holder_new(const gchar *str) { StringHolder *obj = g_object_new(TYPE_STRING_HOLDER, NULL); obj->str = g_strdup(str); // 复制字符串避免外部内存释放导致的问题 return obj; } // 然后就可以用这个类的GType创建GListStore了 GListStore *store = g_list_store_new(TYPE_STRING_HOLDER); StringHolder *holder = string_holder_new("自定义包装的字符串"); g_list_store_append(store, holder); g_object_unref(holder);
最后再提个小注意点:GListStore会自动管理元素的引用计数——添加元素时它会自动ref,移除或销毁列表时会自动unref,所以你添加元素后可以放心unref自己手上的引用,不用手动管理这些元素的内存~
备注:内容来源于stack exchange,提问作者Newbyte
相关产品推荐
相关产品推荐

