1 Classes are objects of metaclasses, so therefore
2 classes are created with NewObjectA().
4 As of now there are three different metaclasses available:
7 - Creates classes that supports multiple interfaces.
10 - Creates classes that can only support single interfaces.
11 Advantage is faster method invocation.
12 (Method invocation doesn't require hashing).
15 - Base metaclass for Hidds. Subclass of CLID_SIMeta.
16 (HIDDs should be fast).
18 How to create a class is best shown through an example.
19 Here is a Timer class with two simple methods,
21 Note, this example doesn't show the New and Dispose
22 methods and DoSuperMethod() usage, but it is exactly the same as in BOOPSI,
23 so those familiar with BOOPSI,should find creating classes with this
27 /* In the classes' include file you have to define class ID, interface ID
28 method offsets and attribute offset
31 /* The IDs below should really be genrated by some tool,
32 as a combination of current time and some machine
33 unique ID, IP address or othe unique entity, to
38 #define CLID_Timer "timerclass"
39 #define IID_Timer "I_timer"
42 /* Method offset for methods in the IID_Timer interface. */
49 Num_Timer_Methods /* number of methods in the Timer interface */
54 /* Attribute offsets for attrs in the IID_Timer interface. */
60 Num_Timer_Attrs /* number of attrs in the timer interface */
64 /* private instance data */
67 struct timeval start_time;
68 struct timeval elapsed_time;
74 static VOID timer_start(Class *cl, Object *o, Msg msg)
76 struct timer_data *data;
78 data = INST_DATA(tcl, o);
80 gettimeofday(&(data->start_time), NULL);
85 static VOID timer_stop(Class *cl, Object *o, Msg msg)
87 struct timer_data *data = INST_DATA(tcl, o);
88 gettimeofday(&(data->elapsed_time), NULL);
90 SubTime(&(data->elapsed_time), &(data->start_time));
96 #define NUM_TIMER_METHODS 2
97 Class *make_timerclass()
100 struct MethodDescr methods[NUM_TIMER_METHODS + 1] =
102 {(IPTR (*)())timer_start, moTimer_Start},
103 {(IPTR (*)())timer_stop, moTimer_Stop},
104 {NULL, 0UL} /* must be null-terminated */
108 struct InterfaceDescr ifdescr[] =
110 { methods, "Timer", NUM_TIMER_METHODS },
111 { NULL, 0UL, 0UL} /* must be null-terminated */
114 struct TagItem tags[] =
116 {A_Meta_SuperID, (IPTR)CLID_Root},
117 {A_Meta_InterfaceDescr, (IPTR)ifdescr},
118 {A_Meta_ID, (IPTR)CLID_Timer},
119 {A_Meta_InstSize, (IPTR)sizeof (struct timer_data)},
126 /* Make it a class of the SIMeta */
127 tcl = (Class *)NewObjectA(NULL, CLID_SIMeta, tags);
132 /* Make the class public */
139 VOID free_timerclass(Class *cl)
141 DisposeObject((Object *)cl);
147 /* Stubs would look like this */
149 VOID Timer_Start(Object *timer)
151 static ULONG mid = NULL;
155 /* First time executed the stub converts the full method ID
156 (String Interface ID, numeric method offset) into a
160 mid = GetMethodID(IID_Timer, moTimer_Start);
163 DoMethod(timer, (Msg)&mid);
169 This API is bound to change, as its not flexible enough
170 (not future-proof), better use tags for specifying all info.
172 Anyway, have a look at the unixio.hidd and hiddclass implementation
173 for a bit more complex usage of this system.