GObject system handles "types".
Q: So what is a "type"?
A: Err.. A "type" is how you consider a piece of data.
See, there is no "type" in assembly language. The data, whether in registers or memory, are what they are treated as. You can always read/write data in "words" which is defined by the processor. If you do multiplication using IMUL insruction (in Intel8088), it is a signed integer. If you use MUL, it is a unsigned integer. Use SHR if you think it is unsigned and use SAR if you think it is signed.
And the C language just help you choose between SHR and SAR according to the "type" of x if you do this:
See, there was no "type" in the processor and "types" is totally man-made. "Types" are introduced in high-level programming languages like C to help deciding what operation can be done on a specific variable. They also help finding programming errors at compile-time when programmers do something which is not supposed to do on a variable of a specific type. This is called "static type checking". Python also have type, but is not checked until the statement is executed, when an exception will be raised.
So much about "type". Let's go to the GObject system.
Q: What is a "Type" in GObject system?
A: Whatever you tell GObject system that it is a type, it is considered a type.
Q: How?
A: Using the g_type_register_xxxxxx() function. Xxxxxx may vary.
Then I'll register a fundamental type with the g_type_register_fundamental() function.
Full code (you can skip this):
Concentrate on this statement and safely ignore everything else.
Q: What is happening?
A: I told GObject that there is a type which is named "MyFirstFundamentalType" and GObject accepted it.
Q: All this simple?
A: Yeah. The only useful information is its name "MyFirstFundamentalType". It needs a type-id (which is an integer) for my fundamental type so I used g_type_fundamental_next().
And then my type is registered successfully. Now my type is now a first-class citizen in the GObject type system just as G_TYPE_INT, G_TYPE_FLOAT, G_TYPE_OBJECT and so on! I can query the name by using g_type_name() function. I can also make other querys about my type as shown in the full code.
// Should those lines below be moved to the next article?
Now I am going to explain the g_type_register_fundamental() function.
Now let's see what information can be provided in the GTypeInfo struct. This struct provides information about your class, including:
- The size of the class and the instances (class_size and instance_size). This means GObject system may help you allocate the memory necessary for your class and instances (it knows their sizes so it can do malloc for you).
- Some functions to initialize and finalize the class and instances.
- How the GValue container would behave.
It doesn't matter if you don't know the difference between a type, a class and an instance. They will be discussed later. GValue will be discussed even later.
GFundamentalInfo is needed by fundamental types. It specifies whether your type is classed (of course not all types are classed, such as int, float and so on), instantiatable (interfaces are not instantiatable) or inheritable.
The GTypeFlags parameter tells it whether the type is abstract.
Q: So what is a "type"?
A: Err.. A "type" is how you consider a piece of data.
See, there is no "type" in assembly language. The data, whether in registers or memory, are what they are treated as. You can always read/write data in "words" which is defined by the processor. If you do multiplication using IMUL insruction (in Intel8088), it is a signed integer. If you use MUL, it is a unsigned integer. Use SHR if you think it is unsigned and use SAR if you think it is signed.
And the C language just help you choose between SHR and SAR according to the "type" of x if you do this:
x >>= 3
See, there was no "type" in the processor and "types" is totally man-made. "Types" are introduced in high-level programming languages like C to help deciding what operation can be done on a specific variable. They also help finding programming errors at compile-time when programmers do something which is not supposed to do on a variable of a specific type. This is called "static type checking". Python also have type, but is not checked until the statement is executed, when an exception will be raised.
So much about "type". Let's go to the GObject system.
Q: What is a "Type" in GObject system?
A: Whatever you tell GObject system that it is a type, it is considered a type.
Q: How?
A: Using the g_type_register_xxxxxx() function. Xxxxxx may vary.
Then I'll register a fundamental type with the g_type_register_fundamental() function.
Full code (you can skip this):
/* A fundamental type. Only its name is significant. */
#include <stdio.h>
#include <glib-object.h>
int main() {
g_type_init(); // This is necessary
GTypeInfo my_type_info = { // This is not important
0, NULL, NULL, NULL, NULL, NULL, 0, 0, NULL, NULL};
GTypeFundamentalInfo my_fundamental_info = {0}; // This is not important
GType my_type_id = g_type_register_fundamental(
g_type_fundamental_next(),
"MyFirstFundamentalType",
&my_type_info,
&my_fundamental_info,
0
);
printf("%s\n",g_type_name(my_type_id));
printf("%s\n",g_type_name(G_TYPE_INT));
printf("%s\n",g_type_name(G_TYPE_FLOAT));
printf("%s\n",g_type_name(G_TYPE_OBJECT));
printf("Type id: %d\n",g_type_from_name("MyFirstFundamentalType"));
printf("Type name: %s\n",g_type_name(g_type_from_name("MyFirstFundamentalType")));
printf("Is abstract? %s\n", G_TYPE_IS_ABSTRACT (my_type_id)? "yes":"no");
printf("Is derived? %s\n", G_TYPE_IS_DERIVED (my_type_id)? "yes":"no");
printf("Is fundamental? %s\n", G_TYPE_IS_FUNDAMENTAL (my_type_id)? "yes":"no");
printf("Is value type? %s\n", G_TYPE_IS_VALUE_TYPE (my_type_id)? "yes":"no");
printf("Has value table? %s\n", G_TYPE_HAS_VALUE_TABLE (my_type_id)? "yes":"no");
printf("Is classed? %s\n", G_TYPE_IS_CLASSED (my_type_id)? "yes":"no");
printf("Is instantiable? %s\n", G_TYPE_IS_INSTANTIATABLE (my_type_id)? "yes":"no");
printf("Is derivable? %s\n", G_TYPE_IS_DERIVABLE (my_type_id)? "yes":"no");
printf("Is deep derivable? %s\n",G_TYPE_IS_DEEP_DERIVABLE(my_type_id)? "yes":"no");
printf("Is interface? %s\n", G_TYPE_IS_INTERFACE (my_type_id)? "yes":"no");
return 0;
}
Concentrate on this statement and safely ignore everything else.
GType my_type_id = g_type_register_fundamental(
g_type_fundamental_next(),
"MyFirstFundamentalType",
&my_type_info,
&my_fundamental_info,
0
);
Q: What is happening?
A: I told GObject that there is a type which is named "MyFirstFundamentalType" and GObject accepted it.
Q: All this simple?
A: Yeah. The only useful information is its name "MyFirstFundamentalType". It needs a type-id (which is an integer) for my fundamental type so I used g_type_fundamental_next().
And then my type is registered successfully. Now my type is now a first-class citizen in the GObject type system just as G_TYPE_INT, G_TYPE_FLOAT, G_TYPE_OBJECT and so on! I can query the name by using g_type_name() function. I can also make other querys about my type as shown in the full code.
// Should those lines below be moved to the next article?
Now I am going to explain the g_type_register_fundamental() function.
GType g_type_register_fundamental (GType type_id,
const gchar *type_name,
const GTypeInfo *info,
const GTypeFundamentalInfo *finfo,
GTypeFlags flags);
Now let's see what information can be provided in the GTypeInfo struct. This struct provides information about your class, including:
- The size of the class and the instances (class_size and instance_size). This means GObject system may help you allocate the memory necessary for your class and instances (it knows their sizes so it can do malloc for you).
- Some functions to initialize and finalize the class and instances.
- How the GValue container would behave.
It doesn't matter if you don't know the difference between a type, a class and an instance. They will be discussed later. GValue will be discussed even later.
GFundamentalInfo is needed by fundamental types. It specifies whether your type is classed (of course not all types are classed, such as int, float and so on), instantiatable (interfaces are not instantiatable) or inheritable.
The GTypeFlags parameter tells it whether the type is abstract.