1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
***FIXME****
Currently annotations are required to be pooled in one place,
sorted by entry offset. That makes it impossible to add annotations
in incremental manner, making it impossible for dynamic languages
like Python to give correct metadata. We should probably remove that
requirement, and add offset to annotations to each annotatable entry,
this however means 4*n more bytes used :\
***FIXME****
mclasen: Incremental generation of metadata is already
problematic without annotations, since you have to grow the
directory, and we currently assume that local entries
are before remote entries in the directory.
Adding 4 bytes to each type, value and arg blob is certainly
going to blow the size of the metadata up unreasonably,
since these are the most common blob types.
Typed annotations:
struct AnnotationBlob
{
guint32 entry_offset;
guint32 type;
guint32 values_offset;
};
entry_offset: offset of metadata entry (must be valid target for this
annotation) described by this annotation
type: offset of AttributeBlob describing type of this annotation
values_offset: offset to n_fields (read from corresponding AttributeBlob)
values of appropriate types, specifying value of this
annotation
mclasen: What type of blob is being pointed to here ?
ValueBlob only holds integer types (for use in enums).
For general types, you will probably have to use
ConstantBlobs.
typedef enum
{
function = 1 << 0,
type = 1 << 1,
param = 1 << 2,
value = 1 << 3,
signal = 1 << 4,
property = 1 << 5,
all = 0x3F,
} AttributeTargets;
mclasen: Does "all" mean just all of the above, or
any blob ? Whats the rationale for not allowing annotations
on some blob types ? Wouldn't it be better to specify
the attribut target using the blob type enum (no way to
specify a subset of targets then, but we could still
indicate "all", e.g. as 0)
struct AttributeBlob
{
guint16 blob_type; /* 11 */
guint deprecated : 1;
guint allow_multiple : 1;
AttributeTargets targets : 6;
guint has_constructor : 1;
guint reserved : 8;
guint32 name;
GTypeBlob gtype;
guint32 constructor;
guint16 n_fields;
FieldBlob fields[];
};
allow_multiple: if that attribute can be applied multiple times to one
annotated entry.
targets: bitmask of allowed targets for annotation with this attribute.
Possible targets are: function (including methods), function
parameter, type (that is, object, enum, or interface), value
(constant or variable exposed from metadata), signal or
property.
has_constructor: if that attribute has constructor. If 0, default constructor
is used.
name: name of this attribute.
gtype: GType under which is the attribute registered.
mclasen: This is unclear. Why would attributes be registered
in GType ? Do we have a special base type for them ? Do
they need to conform to some interface ?
constructor: offset to constructor function for this attribute, or 0 if
default is used.
mclasen: This is unclear. Who uses this constructor, and
what is it used for ?
n_fields: number of fields this attribute has
mclasen: it seems to me that, since we have struct support,
a single field would be sufficient.
fields: array of SimpleTypeBlobs describing fields this attribute has.
Only allowed are types for which valid literals exist. Currently
that's the following types:
void
boolean
int8
uint8
int16
uint16
int32
uint32
int64
uint64
int
uint
long
ulong
ssize_t
size_t
float
double
utf8
filename
type
"type" is guint32 specifying offset to another metadata
entry describing one of: object, interface, enum, function
(including methods), callback, signal or constant. "type"
literals should be exposed to the user either as strings
specyfing fully qualified name of one of above types,
mangled according to rules of language used (if the language
uses any mangling of type names), or type expressed as
valid type literal in syntax of language.
Implementation is responsible for reading such type name and
converting it to correct guint32 value.
mclasen: I would be pragmatic and specify types just be
a qualified name, as you already do in your C example below.
But I think there is a case for allowing arrays of basic
types. I could imagine storing the "Since: 2.6" annotation
as { 2, 6 }
For example, Python might use the following syntax:
gobject.annotation(my_container, ContainerTypeAttribute,
type=gobject.GObject)
Here, my_container is variable of some container class,
ContainerTypeAttribute is hypothetical attribute specifying
specialisation for containers, and type=gobject.GObject says
that this given container will hold GObjects. Python
implementation is now responsible for converting gobject.GObject
into guint32 value pointing to definition of GObject (***FIXME***
how do we deal with GObject which is fundamental type?).
The same expressed in C could look as follows:
G_OBJECT_ANNOTATION(my_container_constant, ContainerTypeAttribute
"type", "GObject.GObject")
where G_OBJECT_ANNOTATION is hypothetical macro used for marking
annotations for metadata scanner.
|