gobject type system

1.  Now, let's say we want to call the C function  function_foo  from a Python program. To do this, the Python interpreter needs to:
  • Find where the function is located. This probably means finding the binary generated by the C compiler which exports this function.

  • Load the code of the function in executable memory.

  • Convert the Python parameters to C-compatible parameters before calling the function.

  • Call the function with the right calling convention.

  • Convert the return values of the C function to Python-compatible variables to return them to the Python code.

2. The process described above is pretty complex and there are a lot of ways to make it entirely automatic and transparent to C and Python programmers:

  • The first solution is to write by hand a lot of glue code, once for each function exported or imported, which does the Python-to-C parameter conversion and the C-to-Python return value conversion. This glue code is then linked with the interpreter which allows Python programs to call Python functions which delegate work to C functions.

  • Another, nicer solution is to automatically generate the glue code, once for each function exported or imported, with a special compiler which reads the original function signature.

  • The solution used by GLib is to use the GType library which holds at runtime a description of all the objects manipulated by the programmer. This so-called dynamic type [1] library is then used by special generic glue code to automatically convert function parameters and function calling conventions between different runtime domains.

3. A lthough that goal was arguably laudable, its pursuit has had a major influence on the whole GType/GObject library. C programmers are likely to be puzzled at the complexity of the features exposed in the following chapters if they forget that the GType/GObject library was not only designed to offer OO-like features to C programmers but also transparent cross-language interoperability.

4.  

undamental and non-fundamental types are defined by:

  • class size: the class_size field in GTypeInfo.

  • class initialization functions (C++ constructor): the base_init and class_init fields in GTypeInfo.

  • class destruction functions (C++ destructor): the base_finalize and class_finalize fields in GTypeInfo.

  • instance size (C++ parameter to new): the instance_size field in GTypeInfo.

  • instantiation policy (C++ type of new operator): the n_preallocs field in GTypeInfo.

  • copy functions (C++ copy operators): the value_table field in GTypeInfo.

  • type characteristic flags: GTypeFlags.

5. some conventions:

There are a number of conventions users are expected to follow when creating new types which are to be exported in a header file:

  • Use the object_method pattern for function names: to invoke the method named foo on an instance of object type bar, call bar_foo.

  • Use prefixing to avoid namespace conflicts with other projects. If your library (or application) is named Maman[3] prefix all your function names with maman_. For example: maman_object_method.

  • Create a macro named PREFIX_TYPE_OBJECT which always returns the GType for the associated object type. For an object of type Bar in a library prefixed by maman, use: MAMAN_TYPE_BAR. It is common although not a convention to implement this macro using either a global static variable or a function named prefix_object_get_type. We will follow the function pattern wherever possible in this document.

  • Create a macro named PREFIX_OBJECT (obj) which returns a pointer of type PrefixObject. This macro is used to enforce static type safety by doing explicit casts wherever needed. It also enforces dynamic type safety by doing runtime checks. It is possible to disable the dynamic type checks in production builds (see building glib). For example, we would create MAMAN_BAR (obj) to keep the previous example.

  • If the type is classed, create a macro named PREFIX_OBJECT_CLASS (klass). This macro is strictly equivalent to the previous casting macro: it does static casting with dynamic type checking of class structures. It is expected to return a pointer to a class structure of type PrefixObjectClass. Again, an example is: MAMAN_BAR_CLASS.

  • Create a macro named PREFIX_IS_BAR (obj): this macro is expected to return a gboolean which indicates whether or not the input object instance pointer of type BAR.

  • If the type is classed, create a macro named PREFIX_IS_OBJECT_CLASS (klass) which, as above, returns a boolean if the input class pointer is a pointer to a class of type OBJECT.

  • If the type is classed, create a macro named PREFIX_OBJECT_GET_CLASS (obj) which returns the class pointer associated to an instance of a given type. This macro is used for static and dynamic type safety purposes (just like the previous casting macros).

6. 
#define MAMAN_TYPE_BAR                  (maman_bar_get_type ())
#define MAMAN_BAR(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAMAN_TYPE_BAR, MamanBar))
#define MAMAN_BAR_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), MAMAN_TYPE_BAR, MamanBarClass))
#define MAMAN_IS_BAR(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAMAN_TYPE_BAR))
#define MAMAN_IS_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MAMAN_TYPE_BAR))
#define MAMAN_BAR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), MAMAN_TYPE_BAR, MamanBarClass))
 
    
 
    
7. 

The following code shows how to implement the maman_bar_get_type function:

GType maman_bar_get_type (void)
{
  static GType type = 0;
  if (type == 0) {
    const GTypeInfo info = {
      /* You fill this structure. */
    };
    type = g_type_register_static (G_TYPE_OBJECT,
                                   "MamanBarType",
                                   &info, 0);
  }
  return type;
}

If you have no special requirements you can use the G_DEFINE_TYPE macro to define a class:

G_DEFINE_TYPE (MamanBar, maman_bar, G_TYPE_OBJECT)

8. 初始化
If this is the first instance of the object ever created, the type system must create a class structure. It allocates a buffer to hold the object's class structure and initializes it. The first part of the class structure (ie: the embedded parent class structure) is initialized by copying the contents from the class structure of the parent class. The rest of class structure is initialized to zero. If there is no parent, the entire class structure is initialized to zero. The type system then invokes the base_class_initialization functions ( GBaseInitFunc ) from topmost fundamental object to bottom-most most derived object. The object's class_init ( GClassInitFunc ) function is invoked afterwards to complete initialization of the class structure. Finally, the object's interfaces are initialized (we will discuss interface initialization in more detail later).
Once the type system has a pointer to an initialized class structure, it sets the object's instance class pointer to the object's class structure and invokes the object's instance_init (GInstanceInitFunc)functions, from top-most fundamental type to bottom-most most derived type.
9. 析构
Class destruction (the concept of destruction is sometimes partly referred to as finalization in GType) is the symmetric process of the initialization: interfaces are destroyed first. Then, the most derived class_finalize (GClassFinalizeFunc) function is invoked. Finally, the base_class_finalize (GBaseFinalizeFunc) functions are invoked from bottom-most most-derived type to top-most fundamental type and the class structure is freed.

10. 总结

The instantiation/finalization process can be summarized as follows:

Table 1. GType Instantiation/Finalization

Invocation timeFunction InvokedFunction's parameters
First call tog_type_create_instance for target typetype's base_init functionOn the inheritance tree of classes from fundamental type to target type. base_init is invoked once for each class structure.
target type's class_init functionOn target type's class structure
interface initialization, see the section called “Interface Initialization” 
Each call tog_type_create_instance for target typetarget type's instance_init functionOn object's instance
Last call tog_type_free_instance for target typeinterface destruction, see the section called “Interface Destruction” 
target type's class_finalize functionOn target type's class structure
type's base_finalize functionOn the inheritance tree of classes from fundamental type to target type. base_finalize is invoked once for each class structure.

11. 接口初始化

When an instantiable classed type which implements an interface (either directly or by inheriting an implementation from a superclass) is created for the first time, its class structure is initialized following the process described in the section called “Instantiable classed types: objects”. After that, the interface implementations associated with the type are initialized.

First a memory buffer is allocated to hold the interface structure. The parent's interface structure is then copied over to the new interface structure (the parent interface is already initialized at that point). If there is no parent interface, the interface structure is initialized with zeros. The g_type and the g_instance_type fields are then initialized: g_type is set to the type of the most-derived interface and g_instance_type is set to the type of the most derived type which implements this interface.


12. 接口初始化总结

Table 2. Interface Initialization

Invocation timeFunction InvokedFunction's parametersRemark
First call tog_type_create_instance forany type implementing interfaceinterface'sbase_initfunctionOn interface's vtableRarely necessary to use this. Called once per instantiated classed type implementing the interface.
First call tog_type_create_instance foreach type implementing interfaceinterface'sdefault_initfunctionOn interface's vtableRegister interface's signals, properties, etc. here. Will be called once.
First call tog_type_create_instance forany type implementing interfaceimplementation'sinterface_initfunctionOn interface's vtableInitialize interface implementation. Called for each class that that implements the interface. Initialize the interface method pointers in the interface structure to the implementing class's implementation.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值