`
cloverprince
  • 浏览: 129827 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

GObject 02: A classed type

阅读更多
Now I am going to create a classed type.

Q: What is a class?
A: I don't know for sure.  In object-oriented programming, a class represents a "kind" of data.  It specifies what data there is (the members/fields) in each object (instance) and what can be done (the methods) to the object.

Q: What is a "classed" type in GObject?
A: It is a type that has a "class struct".

Each "classed type" has a unique instance of "class structure".  Note that IN GOBJECT, THERE IS A DIFFERENCE BETWEEN A "Class" AND AN "Instance".  A "Class" IS SOMETHING THAT IS SHARED BY ALL OBJECTS OF A CLASS AND AN "Instance" IS SOMETHING THAT IS SPECIFIC TO EACH OBJECT OF THE CLASS.  You can imagine that whatever in a "Class" are like the static members/fields in C++/Java and whatever in an "Instance" are like non-static members/fields.

The code is here:
/* A fundamental type.  It has a class structure, but is not instantiable. */

#include <stdio.h>
#include <glib-object.h>

typedef struct {
    GTypeClass something_as_boilerplate;
    int foo;
    char* bar;
    void (*baz)();
} myclass_t;

void baz_function() { printf("All your type are belong to us!\n"); }

void my_class_init_func(myclass_t* klass, gpointer data) {
    printf("my_class_init_func called!\n");
    klass->foo = 42;
    klass->bar = "Hello world!";
    klass->baz = baz_function;
}

int main() {
    g_type_init();

    GTypeInfo my_type_info = {
        sizeof(myclass_t),  //guint16                class_size;

        NULL,               //GBaseInitFunc          base_init;
        NULL,               //GBaseFinalizeFunc      base_finalize;

        /* classed types, instantiated types */
        (GClassInitFunc)my_class_init_func, //GClassInitFunc         class_init;
        NULL,               //GClassFinalizeFunc     class_finalize;
        NULL,               //gconstpointer          class_data;

        /* instantiated types */
        0,                  //guint16                instance_size;
        0,                  //guint16                n_preallocs;
        NULL,               //GInstanceInitFunc      instance_init;

        /* value handling */
        NULL,               //const GTypeValueTable *value_table;
    };

    GTypeFundamentalInfo my_fundamental_info = {
        G_TYPE_FLAG_CLASSED
    };

    GType my_type_id = g_type_register_fundamental(
            g_type_fundamental_next(),
            "MyClassedFundamentalType",
            &my_type_info,
            &my_fundamental_info,
            0
            );

    printf("%d\n",my_type_id);
    printf("%s\n",g_type_name(my_type_id));

    myclass_t *klass = (myclass_t*)g_type_class_ref(my_type_id);
    
    printf("foo: %d\n", klass->foo);
    printf("bar: %s\n", klass->bar);
    klass->baz();

    g_type_class_unref(klass);

    return 0;
}


Let's look at the my_type_info struct in the main function.  I filled the class_size field to be sizeof(myclass_t) so that the type-system can help me "malloc" my myclass_t struct.  I also filled the class_init function so that it will call my my_class_init_func to initialize it.

But I didn't fill the instance_size or instance_init so it is not instantiatable.  That is, this type has no instances.

Q: How can it be it useful to have such a type that has no instances?
A: Well... I admit it is not that useful.  It may work as something like a "singleton" (a globally unique object).  Interfaces (like they are in Java/C#) in GObject are also non-instantiatable types.

Then the my_fundamental_info struct following the my_type_info variable in the main function.  I marked this class as "classed".


Let's look at my myclass_t structure. 

Q: Why don't you follow the GObject naming convention and name it as MyClass?
A: It is intentional.  I am emphasizing that it is not the naming-convention, but the function calls (like g_type_register_fundamental) and its parameters (like GTypeInfo, GTypeFundamentalInfo and so on) that make GObject work.  Yeah, you should follow the convention in real-world programming.

typedef struct {
    GTypeClass something_as_boilerplate;
    int foo;  // Not a good idea to store data here.
    char* bar;
    void (*baz)();
} myclass_t;


The first member is a GTypeClass field.  It is required that in GObject type system, all class-structs should begin with a GTypeClass field.

Q: What's inside the GTypeClass?
A: The documentation does not tell me.  The source code is:
typedef struct _GTypeClass              GTypeClass;
struct _GTypeClass
{
  /*< private >*/
  GType g_type;
};


So every class struct starts with a GType field (GType is typedef'ed to be gsize which is then typedef'ed to be unsigned int).  This can be queryed at runtime to find the type-id (GType) of a type.

Then there are an int field "foo", a char pointer "bar" and a function pointer "baz" in myclass_t struct.  foo and bar are static members of my class.  baz, which you may think to be a static member, can also be a virtual method of a class (this will be discussed later).

Let's move on to the my_class_init_func which I filled into the class_init field of the "GTypeInfo my_type_info" struct.
void my_class_init_func(myclass_t* klass, gpointer data) {
    printf("my_class_init_func called!\n");
    klass->foo = 42;
    klass->bar = "Hello world!";
    klass->baz = baz_function;
}


It takes two parameters.  One of them is a myclass_t pointer pointing to the struct to be initialized.  I name it "klass" because "class" is a keyword in C++ and would not work with a C++ compiler.  The other is the class_data field provided in the GTypeInfo struct (where I set it to NULL).

I initialized the myclass_t struct here.  I filled the foo, bar and baz field.


Now the main function.  Here I register my type.  And then:
    myclass_t *klass = (myclass_t*)g_type_class_ref(my_type_id);
    
    printf("foo: %d\n", klass->foo);
    printf("bar: %s\n", klass->bar);
    klass->baz();

    g_type_class_unref(klass);

I call the g_type_class_ref function so that my class struct is initialized.  Then the members of klass are filled.  Finally I call the g_type_class_unref(klass) to unref this class (this may be not necessary here).


Note that it is not a good idea to store static data member into the class struct.  It is difficult to get a pointer to the class struct without having an instance of this class.  You may wish to access the class member in the main function or in a static function.  It is better to use global variables and use naming conventions to show that they belong to a class.

分享到:
评论

相关推荐

    Giveda_GObject_c++11_v1.5

    利用本软件,c++开发者可以在不依赖c++编译器之外的任何工具的前提下,实现c++中类与类之间的解耦合(class A对象与class B对象之间的解耦合)。 本软件支持c++11并向后兼容(支持c++11及其后续版本)。 开发环境为...

    GObject Reference Manual

    Generic Values - A polymorphic type that can hold values of any other type Parameters and Values - Standard Parameter and Value Types Varargs Value Collection - Converting varargs to generic values ...

    gobject-snippets:UltiSnips C 片段有助于编写 GObject 代码

    UltiSnips C 片段有助于编写 GObject 代码 安装 这些片段使用 UltiSnips ( ) 所以你应该先安装和配置它。 我使用 Vundle ( ) 来管理 vim 插件,但这不是强制性的。 如果你使用 Vundle,你可以添加到你的 ~/.vimrc ...

    Gobject 离线API手册

    GObject是GTK+库的核心组件,它为C语言提供了一种面向对象的编程模型。在GTK+和Gnome开发中,GObject系统是构建复杂、可扩展软件的基础。这个离线API手册包含了GObject框架的详细信息,对于理解并利用GObject进行...

    crystal-gobject:Crystal的gobject-introspection

    crystal-gobject:Crystal的gobject-introspection

    Gobject Reference Manual

    8. 继承:GObject支持类的继承,通过g_type_class_ref()和g_type_class_peek()等函数可以访问父类的方法和属性。 9. 错误处理:GObject提供了一套错误系统,允许对象在遇到错误时发出错误信息,通过GError结构体和g...

    groonga-gobject:Groonga的GObject包装器

    Groonga GObject 描述 Groonga的GObject包装器。 去做... 安装 Debian GNU / Linux 。 运行以下命令: % sudo apt-get install -V -y gir1.2-groonga libgroonga-gobject0 的Ubuntu 。 运行以下命令: % ...

    Gobject 资料,全面介绍

    Gobject 资料,全面介绍Gobject 资料,全面介绍Gobject 资料,全面介绍Gobject 资料,全面介绍Gobject 资料,全面介绍Gobject 资料,全面介绍Gobject 资料,全面介绍

    gobject_setup_property_demo.zip

    在IT领域,特别是软件开发中,GObject是一个关键的概念,它是GTK+库中的基础对象模型。GObject系统为C语言提供了面向对象编程的支持,而这个"gobject_setup_property_demo.zip"压缩包显然提供了一个关于如何使用...

    gobject:适用于PHP的静态Gobject绑定

    gtkforphp gobject扩展为GObject功能提供了语言绑定。 有关该库的文档和信息可以在找到 现在,这只不过是一个占位符。 您可以发送评论,补丁,问题 这仍然是实验性的扩展。 安装/配置 此扩展需要gtkforphp / glib...

    gobject_create_class_demo.tar.gz

    本示例用于演示GObject创建新类,类的继承与重载。代码实现了shape和square类,继承关系为: square -&gt; shape -&gt;gobject 其中,square重载了shape类的info接口。

    yard-gobject-introspection:YARD插件,用于从GObject Introspection数据检索文档

    码-对象反省码插件,用于基于GObject-Intropection构建库文档。要求Ruby / GObject-Introspection尝试一下 git clone ...

    gobject对象系统

    在使用任何GType或GObject之前,必须调用`g_type_init()`来初始化类型系统。`GType`提供了注册和管理所有基本数据类型、用户定义的对象和接口类型的技术实现。 ##### 2. 类型注册 (Type Registration) GObject支持...

    cairo-gobject-1.15.12-3.el7.x86_64.rpm

    离线安装包,亲测可用

    python3-pygobject3:GObject库的Python 3绑定

    3. **对象创建与实例化**:Python中的GObject子类可以像普通Python类一样实例化,但它们通常会调用`GObject.Object()`作为基类,并且可能需要通过`GObject.type_register`进行类型注册。 4. **属性和信号**:在...

    GObject对象系统

    为了确保类型系统的正确初始化,在使用任何`GType`或`GObject`的功能之前,必须调用`g_type_init()`函数。 - **静态类型与动态类型**: - **静态类型**:这些类型是在编译时确定的,不能在运行时动态地加载或卸载...

    lgi:使用GObject-Introspection将动态Lua绑定到GObject库

    液化天然气LGI是基于gobject内省的动态Lua绑定到基于GObject的库。 它允许直接从Lua使用基于GObject的库。 已获得许可的许可,请参见LICENSE文件全文。 该项目的主页位于。 LGI经过测试,并与标准Lua 5.1,Lua 5.2,...

    gir_ffi, 在运行时使用 FFI,为基于GObject的库自动生成绑定.zip

    gir_ffi, 在运行时使用 FFI,为基于GObject的库自动生成绑定 GirFFI由 Matijs van Zuijlen描述使用GObject内省存储库的GNOME的ruby 绑定。状态 特性为基于任何gobject的库创建绑定。在运行时生成绑定。为选定方法...

    python-gobject-3.22.0-1.el7_4.1.x86_64.rpm

    离线安装包,亲测可用

    avahi-gobject-0.6.25-11.el6.i686.rpm

    avahi-gobject-0.6.25-11.el6.i686.rpm是centos工具包。

Global site tag (gtag.js) - Google Analytics