GObject 03: An Instantiatable Class

GObject 03: An Instantiatable Class
2011年08月01日
   Most of the time classes are instantiatable. It can create "instances", which have their own data and share common methods of the class.
  So a CLASS is shared by many INSTANCEs.
  In GObject, we need two structs. One for the class and one for the instance.
  /* A fundamental type. Instantiatable. */ #include #include typedef struct { GTypeClass something_as_boilerplate; } myclass_t; int a_class_member_of_myclass; typedef struct { GTypeInstance something_as_boilerplate; int an_instance_member; } myinstance_t; void my_class_method() { printf("The class member is %d\n", a_class_member_of_myclass); } void my_instance_method(myinstance_t *instance, int a_parameter) { printf("The member is %d\n",instance->an_instance_member); printf("The parameter is %d\n",a_parameter); } void my_class_init_func(myclass_t* klass, gpointer data) { printf("my_class_init_func called!\n"); a_class_member_of_myclass = 42; } void my_instance_init_func(myinstance_t *instance, gpointer data) { printf("my_instance_init_func called!\n"); instance->an_instance_member = 65; } 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 */ sizeof(myinstance_t),//guint16 instance_size; 0, //guint16 n_preallocs; (GInstanceInitFunc)my_instance_init_func, //GInstanceInitFunc instance_init; /* value handling */ NULL, //const GTypeValueTable *value_table; }; GTypeFundamentalInfo my_fundamental_info = { G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE }; GType my_type_id = g_type_register_fundamental( g_type_fundamental_next(), "MyInstantiatableFundamentalType", &my_type_info, &my_fundamental_info, 0 ); printf("%d\n",my_type_id); printf("%s\n",g_type_name(my_type_id)); myinstance_t *instance = (myinstance_t*)g_type_create_instance(my_type_id); my_instance_method(instance,78); my_class_method(); printf("Is instance of class? %s\n", G_TYPE_CHECK_INSTANCE_TYPE(instance, my_type_id)?"yes":"no"); printf("Is instance of class? %s\n", G_TYPE_CHECK_INSTANCE_TYPE(instance, G_TYPE_INT)?"yes":"no"); return 0; }
  And focus in here:
  typedef struct { GTypeClass something_as_boilerplate; } myclass_t; int a_class_member_of_myclass; typedef struct { GTypeInstance something_as_boilerplate; int an_instance_member; } myinstance_t;
  Q: What are the something_as_boilerplate things?
  A: As every other classes in GObject, all class structs start with a GTypeClass field and all instance structs start with a GTypeInstance field.
  Q: What do they contain?
  A: GTypeClass contains a GType which shows its type. GTypeInstance contains a pointer to its class struct so every instance knows its class. See the source code to make sure.
  Q: Where are their members/fields?
  A: Non-static members (such as an_instance_member) are in the instance struct, after the GTypeInstace. Static members (such as a_class_member_of_myclass) are usually global and are usually not in the class struct(see the previous article).
  Q: How do you figure out if it is a member or a global variable?
  A: You say "let it be a member" and it is a member. The concepts "object-oriented programming", "class", "instance" and "member" are all man-made so it is a member if you treat it like a member.
  And the functions:
  void my_class_method() { printf("The class member is %d\n", a_class_member_of_myclass); } void my_instance_method(myinstance_t *instance, int a_parameter) { printf("The member is %d\n",instance->an_instance_member); printf("The parameter is %d\n",a_parameter); }
  Q: What are methods like?
  A: Methods are simply functions. Non-static methods always take a pointer to an instance struct as their first parameter. Static methods are ordinary functions.
  Q: How do you figure out if it is a member or a global variable?
  A: You say "let it be a method" and it is a method. The concept "method" is man-made so it is a method if you treat it like a method.
  Now we ask GLib to recognize my class as a type.
  Code from the main() function:
  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 */ sizeof(myinstance_t),//guint16 instance_size; 0, //guint16 n_preallocs; (GInstanceInitFunc)my_instance_init_func, //GInstanceInitFunc instance_init; /* value handling */ NULL, //const GTypeValueTable *value_table; }; GTypeFundamentalInfo my_fundamental_info = { G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE }; GType my_type_id = g_type_register_fundamental( g_type_fundamental_next(), "MyInstantiatableFundamentalType", &my_type_info, &my_fundamental_info, 0 );
  Again we use the g_type_register_fundamental() function to make the library think myclass is a class whose instance is myinstance.
  We provide one GTypeInfo struct. class_size and instance_size are filled so that the library can automatically malloc a myclass_t struct and some myinstance_t structs. class_init and instance_init are also provided so that the library can help me initialize the class/instance struct when they are created.
  In GTypeFundamentalInfo, mark my class as CLASSED and INSTANTIATABLE.
  Register it with g_type_register_fundamental and then it becomes a type.
  And the init functions:
  void my_class_init_func(myclass_t* klass, gpointer data) { printf("my_class_init_func called!\n"); a_class_member_of_myclass = 42; } void my_instance_init_func(myinstance_t *instance, gpointer data) { printf("my_instance_init_func called!\n"); instance->an_instance_member = 65; }
  They initialize the class and the instance, respectively on creating. You can omit them if they are not necessary.
  Now the main() function:
  printf("%d\n",my_type_id); printf("%s\n",g_type_name(my_type_id)); myinstance_t *instance = (myinstance_t*)g_type_create_instance(my_type_id); my_instance_method(instance,78); my_class_method(); printf("Is instance of class? %s\n", G_TYPE_CHECK_INSTANCE_TYPE(instance, my_type_id)?"yes":"no"); printf("Is instance of class? %s\n", G_TYPE_CHECK_INSTANCE_TYPE(instance, G_TYPE_INT)?"yes":"no");
  g_type_name querys the string representation of the name of the type.
  When first creating an instance using g_type_create_instance, the class struct is automatically allocated and initialized.
  In order to call a instance method, just call the function with the first argument filled as the instance pointer.
  G_TYPE_CHECK_INSTANCE_TYPE checks the type of an instance.
  Q: How can it know the type of the instance by merely a pointer to the instance?
  A: Recall that the first field of myinstance_t (that is GTypeInstance) contains a pointer which points to its class struct (myclass_t) which begins with a GTypeClass which has a GType field which identifies its type.
  This means GObject provides runtime type information (RTTI) support which C++ classes do not usually have. Note that you need to #include in C++ in order to use RTTI.
  
  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值