|
| 1 | +{0 Introduction} |
| 2 | + |
| 3 | +The Ctypes bindings to the GObject-Introspection (all the files/modules named |
| 4 | +[GISomething]). |
| 5 | + |
| 6 | +{1 Implementation details} |
| 7 | + |
| 8 | +{2 GObjectIntrospection Info Structures hierarchy and type coercion functions} |
| 9 | + |
| 10 | +{[ |
| 11 | +GIBaseInfo |
| 12 | + +----GIArgInfo |
| 13 | + +----GICallableInfo |
| 14 | + +----GIFunctionInfo |
| 15 | + +----GISignalInfo |
| 16 | + +----GIVFuncInfo |
| 17 | + +----GIConstantInfo |
| 18 | + +----GIFieldInfo |
| 19 | + +----GIPropertyInfo |
| 20 | + +----GIRegisteredTypeInfo |
| 21 | + +----GIEnumInfo |
| 22 | + +----GIInterfaceInfo |
| 23 | + +----GIObjectInfo |
| 24 | + +----GIStructInfo |
| 25 | + +----GIUnionInfo |
| 26 | + +----GITypeInfo |
| 27 | +]} |
| 28 | + |
| 29 | +This hierarchy determines the need to cast structures. For example [GIArgInfo] |
| 30 | +needs only to be casted to [GIBaseInfo]. |
| 31 | + |
| 32 | +[GIFunctionInfo] needs to be casted to [GICallableInfo] and to [GIBaseInfo]. |
| 33 | + |
| 34 | +So each module will (except GIBaseInfo), have functions for type coercion like: |
| 35 | + |
| 36 | +{[ |
| 37 | + GIArgInfo.to_baseinfo |
| 38 | + GIArgInfo.from_baseinfo |
| 39 | + GIFunctionInfo.to_baseinfo |
| 40 | + GIFunctionInfo.from_baseinfo |
| 41 | + GIFunctionInfo.to_callableinfo |
| 42 | + GIFunctionInfo.from_callableinfo |
| 43 | +]} |
| 44 | + |
| 45 | +{2 How the underlying C structures allocation and deallocation are handled} |
| 46 | + |
| 47 | +When an info structure pointer is returned with full transfert via the C api, |
| 48 | +each OCaml value that wraps them is finalised with [Gc.finalise] for example: |
| 49 | + |
| 50 | +{[ |
| 51 | +let get_field info n = |
| 52 | + let get_field_raw = |
| 53 | + foreign "g_struct_info_get_field" |
| 54 | + (ptr structinfo @-> int @-> returning (ptr GIFieldInfo.fieldinfo)) in |
| 55 | + let max = get_n_fields info in |
| 56 | + if (n < 0 || n >= max) then raise (Failure "Array Index out of bounds") |
| 57 | + else let info' = get_field_raw info n in |
| 58 | + GIFieldInfo.add_unref_finaliser info' |
| 59 | +]} |
| 60 | + |
| 61 | +So when the [info'] value is garbage collected, the |
| 62 | +[GIFieldInfo.add_unref_finaliser] is called. Here is the code of this function: |
| 63 | + |
| 64 | +{[ |
| 65 | +let add_unref_finaliser info = |
| 66 | + let _ = Gc.finalise (fun i -> |
| 67 | + let i' = cast_to_baseinfo i in |
| 68 | + GIBaseInfo.base_info_unref i') info |
| 69 | + in info |
| 70 | +]} |
| 71 | + |
| 72 | +Each info module have this kind of function but the end user of the lib should |
| 73 | +not use them. When a cast need to be done, each module have the following two |
| 74 | +functions: |
| 75 | + |
| 76 | +{ul {- [to_baseinfo]} |
| 77 | + {- [from_baseinfo] }} |
| 78 | + |
| 79 | +Those functions allow to transform an OCaml value that represents a [GIInfo] to |
| 80 | +another [GIInfo] type while the underlying C structure are ref'ed and linked to |
| 81 | +a Gc finaliser that unref them. This should avoid zombies OCaml values (with C |
| 82 | +structure already deallocated) and memory leaks. |
| 83 | + |
| 84 | +{1 Progress} |
| 85 | + |
| 86 | +{2 Finished} |
| 87 | + |
| 88 | +{ul {- GIRepository — GObject Introspection repository manager} |
| 89 | + {- GIBaseInfo — Base struct for all GITypelib structs} |
| 90 | + {- GIFunctionInfo — Struct representing a function} |
| 91 | + {- GIStructInfo — Struct representing a C structure} |
| 92 | + {- GIFieldInfo — Struct representing a struct or union field} |
| 93 | + {- GIUnionInfo — Struct representing a union.} |
| 94 | + {- GIEnumInfo — Structs representing an enumeration and its values} |
| 95 | + {- GIValueInfo — Struct representing a value} |
| 96 | + {- GICallableInfo — Struct representing a callable} |
| 97 | + {- GIArgInfo — Struct representing an argument} |
| 98 | + {- GITypeInfo — Struct representing a type} |
| 99 | + {- GIConstantInfo — Struct representing a constant} |
| 100 | + {- GIObjectInfo — Struct representing a GObject} |
| 101 | + {- GIInterfaceInfo — Struct representing a GInterface} |
| 102 | + {- GIPropertyInfo — Struct representing a property} |
| 103 | + {- GISignalInfo — Struct representing a signal} |
| 104 | + {- GIVFuncInfo — Struct representing a virtual function} |
| 105 | + {- GIRegisteredTypeInfo — Struct representing a struct with a GType}} |
| 106 | + |
| 107 | +{2 Remains} |
| 108 | + |
| 109 | +{ul {- GICallbackInfo — Struct representing a callback (no C API for now).}} |
| 110 | + |
| 111 | +{1 Resources} |
| 112 | + |
| 113 | +{ul {- {{: https://ocaml.org/learn/tutorials/calling_c_libraries.html}}} |
| 114 | + {- {{: https://developer.gnome.org/gi/}}} |
| 115 | + {- {{: https://developer.gnome.org/gi/1.52/GIRepository.html}}} |
| 116 | + {- {{: https://ocaml.org/learn/tutorials/objects.html}}} |
| 117 | + {- {{: https://ocaml.org/manual/index.html}}} |
| 118 | + {- {{: https://ocaml.org/manual/intfc.html}}} |
| 119 | + {- {{: https://web.archive.org/web/20200223115730/http://www.linux-nantes.org/~fmonnier/OCaml/ocaml-wrapping-c.html} http://www.linux-nantes.org/~fmonnier/OCaml/ocaml-wrapping-c.html} (old)} |
| 120 | + {- {{: https://wiki.haskell.org/GObjectIntrospection}}}} |
0 commit comments