source: trunk/python/experimental/include/class.h @ 273

Last change on this file since 273 was 198, checked in by tim, 15 years ago

misc tweaks to run under python2.5-dbg

File size: 14.3 KB
Line 
1/***************************************************
2  Classes and objects in C
3
4  This file makes it easy to implement classes and objects in C. To
5  define a class we need to perform three steps:
6
7  Define the class prototype. This is suitable to go in a .h file for
8  general use by other code.
9
10  Note all classes extend Object.
11
12  Example::
13
14CLASS(Foo, Object)
15    int x;
16    int y;
17
18    //This declares a method of a class Foo, called Con returning a
19    //Foo object. In other words it is a constructor.
20    Foo METHOD(Foo, Con, int x, int y);
21    int METHOD(Foo, add);
22
23END_CLASS
24
25Now we need to define some functions for the constructor and
26methods. Note that the constuctor is using ALLOCATE_CLASS to allocate
27space for the class structures. Callers may call with self==NULL to
28force allocation of a new class. Note that we do not call the
29constructor of our superclass implicitly here. (Calling the sperclass
30constructor is optional, but ALLOCATE_CLASS is not.).
31
32Foo Foo_Con(Foo self,int x,int y) {
33  self->x = x;
34  self->y = y;
35
36  return self;
37};
38
39int Foo_add(Foo this) {
40  return (this->x + this->y);
41};
42
43Now we need to define the Virtual function table - These are those
44functions and attributes which are defined in this class (over its
45superclass). Basically these are all those things in the class
46definition above, with real function names binding them. (Note that by
47convention we preceed the name of the method with the name of the
48class):
49
50VIRTUAL(Foo,Object)
51   VMETHOD(Con) = Foo_Con;
52   VMETHOD(add) = Foo_add;
53END_VIRTUAL
54
55We can use inheritance too:
56
57CLASS(Bar, Foo)
58   Bar METHOD(Bar, Con, char *something)
59END_CLASS
60
61Here Bar extends Foo and defines a new constructor with a different prototype:
62
63VIRTUAL(Bar,Foo)
64   VMETHOD(Con) = Bar_Con
65END_VIRTUAL
66
67If there is a function which expects a Foo, we will need to over ride
68the Foo constructor in the Bar, so the function will not see the
69difference between the Foo and Bar:
70
71CLASS(Bar,Foo)
72  int bar_attr;
73END_CLASS
74
75Foo Bar_Con(Foo self, int x, int y) {
76...
77}
78
79VIRTUAL(Bar, Foo)
80  VMETHOD(super.Con) = Bar_Con
81END_VIRTUAL
82
83Note that in this case we are over riding the Con method defined in
84Foo while creating derived Bar classes. The notation in the VIRTUAL
85table is to use super.Con, because Foo's Con method (the one we are
86over riding), can be located by using super.Con inside a Bar object.
87
88Imagine now that in Bar_Con we wish to use methods and attributes
89defined in Bar. Since Bar_Con over rides Bar's base class (Foo) it
90must have the prototype described above. Since self is of type Foo its
91impossible to use self->bar_attr (There is no bar_attr in Foo - its in
92Bar).
93
94In this case, we need to make a type cast to convice C that self is
95actually a Bar not a Foo:
96
97Foo Bar_Con(Foo self, int x, int y) {
98   Bar this = (Bar)self;
99
100   this->bar_attr=1
101};
102
103This allows us to access bars attributes.
104
105This is a general oddity with C style classes, which C++ and Java
106hide. In C we must always know which class defines which method and
107attribute and reference the right class's method. So for example if we
108want to call a Bar's add method:
109
110Bar a;
111
112a->super.add()
113
114because add is defined in Bar's super class (Foo). Constract this with
115C++ or Java which hide where methods are defined and simply make all
116methods appear like they were defined inside the derived class. This
117takes a while to get used to but the compiler will ensure that the
118references are correct - otherwise things will generally not compile
119properly.
120
121This difference can be used for good and bad. It is possible in C to
122call the base class's version of the method at any time (despite the
123fact it was over ridden).
124
125For example:
126
127CLASS(Derived, Foo)
128      int METHOD(Derived, add);
129END_CLASS
130
131VIRTUAL(Derived, Foo)
132   VMETHOD(add) = Derived_add
133END_VIRTUAL
134
135If d is a Derived object, we can call Foo's version like this:
136d->super.add()
137
138But Derived's version is accessed by:
139d->add()
140
141Sometimes a derived class may want to over ride the base class's
142methods as well, in this case the VIRTUAL section should over ride
143super.add as well.
144
145*/
146/******************************************************
147# Copyright 2004: Commonwealth of Australia.
148#
149# Developed by the Computer Network Vulnerability Team,
150# Information Security Group.
151# Department of Defence.
152#
153# Michael Cohen <scudette@users.sourceforge.net>
154#
155# ******************************************************
156#  Version: FLAG  $Version: 0.87-pre1 Date: Thu Jun 12 00:48:38 EST 2008$
157# ******************************************************
158#
159# * This program is free software; you can redistribute it and/or
160# * modify it under the terms of the GNU General Public License
161# * as published by the Free Software Foundation; either version 2
162# * of the License, or (at your option) any later version.
163# *
164# * This program is distributed in the hope that it will be useful,
165# * but WITHOUT ANY WARRANTY; without even the implied warranty of
166# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
167# * GNU General Public License for more details.
168# *
169# * You should have received a copy of the GNU General Public License
170# * along with this program; if not, write to the Free Software
171# * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
172# ******************************************************/
173#ifndef __CLASS_H__
174#define __CLASS_H__
175
176#ifdef __cplusplus
177extern "C" {
178#endif
179
180
181#ifdef min
182#undef min
183#endif
184#define min(X, Y)  ((X) < (Y) ? (X) : (Y))
185
186#ifdef max
187#undef max
188#endif
189#define max(X, Y)  ((X) > (Y) ? (X) : (Y))
190
191
192#include <talloc.h>
193
194#define CLASS(class,super_class)                                 \
195  typedef struct class ## _t *class;                             \
196  int class ## _init(Object self);                               \
197  extern struct class ## _t __ ## class;                         \
198  struct class ## _t { struct super_class ## _t super;           \
199  class   __class__;                                             \
200  super_class  __super__;
201
202
203#define METHOD(cls, name, ... )         \
204  (* name)(cls self, ## __VA_ARGS__ )
205
206  // Class methods are attached to the class but are not called with
207  // an instance. This is similar to the python class method or java
208  // static methods.
209#define CLASS_METHOD(name, ... )                \
210  (*name)(__VA_ARGS__)
211
212/***************************************************
213   This is a convenience macro which may be used if x if really large
214
215***************************************************/
216#define CALL(x, method, ... )                   \
217  (x)->method((x), ## __VA_ARGS__)
218
219#define END_CLASS };
220
221/***************************************************
222   This is used to set the classes up for use:
223
224   class_init = checks the class template (__class) to see if it has
225   been allocated. otherwise allocates it in the global context.
226
227   class_Alloc = Allocates new memory for an instance of the
228   class. This is a recursive function calling each super class in
229   turn and setting the currently over ridden defaults. So for eample
230   suppose this class (foo) derives from bar, we first fill the
231   template with bars methods, and attributes. Then we over write
232   those with foos methods and attributes.
233
234**********************************************************/
235#define VIRTUAL(class,superclass)                               \
236  struct class ## _t __ ## class;                                       \
237                                                                        \
238  int class ## _init(Object this) {                                    \
239  class self = (class)this;                                             \
240  if(self->__super__) return 1;                                         \
241  superclass ##_init(this);                                             \
242  this->__class__ = (Object)&__ ## class;                               \
243  self->__class__ = (class)&__ ## class;                               \
244  this->__super__ = (Object)&__ ## superclass;                          \
245  self->__super__ = (superclass)&__ ## superclass;                      \
246  this->__size = sizeof(struct class ## _t);                            \
247  this->__name__ = #class;
248
249#define SET_DOCSTRING(string)                   \
250  ((Object)self)->__doc__ = string
251
252#define END_VIRTUAL return 1; }
253
254#define VMETHOD(method)                         \
255  (self)->method
256
257#define VMETHOD_BASE(base, method)              \
258  (((base)self)->method)
259
260#define CLASS_ATTR(self, base, method)          \
261  (((base)self)->method)
262
263#define VATTR(attribute)                        \
264  (self)->attribute
265
266#define NAMEOF(obj)                             \
267  ((Object)obj)->__name__
268
269#define SIZEOF(obj)                             \
270  ((Object)obj)->__size
271
272#define DOCSTRING(obj)                          \
273  ((Object)obj)->__doc__
274
275#define INIT_CLASS(class)                       \
276  class ## _init((Object)&__ ## class)
277
278/*************************************************************
279   This MACRO is used to construct a new Class using a constructor.
280
281    This is done to try and hide the bare (unbound) method names in
282    order to prevent name space pollution. (Bare methods may be
283    defined as static within the implementation file). This macro
284    ensures that class structures are initialised properly before
285    calling their constructors.
286
287   We require the following args:
288    class - the type of class to make
289    virt_class - The class where the method was defined
290    constructors - The constructor method to use
291    context - a talloc context to use.
292
293
294    Note that the class and virt_class do not have to be the same if
295    the method was not defined in the current class. For example
296    suppose Foo extends Bar, but method is defined in Bar but
297    inherited in Foo:
298
299    CONSTRUCT(Foo, Bar, super.method, context)
300
301    virt_class is Bar because thats where method was defined.
302*************************************************************/
303
304// The following only initialises the class if the __super__ element
305// is NULL. This is fast as it wont call the initaliser unnecessaily
306#define CONSTRUCT(class, virt_class, constructor, context, ... )        \
307  (class)( __## class.__super__ == NULL ?                               \
308           class ## _init((Object)&__ ## class) : 0,                    \
309           __## virt_class.__super__ == NULL ?                          \
310           virt_class ## _init((Object)&__ ## virt_class): 0,           \
311             ((virt_class)(&__ ## class))->constructor(                 \
312                       (virt_class)_talloc_memdup(context, &__ ## class, sizeof(struct class ## _t),  __location__ "(" #class ")"), \
313                                   ## __VA_ARGS__) )
314
315/** This variant is useful when all we have is a class reference
316    (GETCLASS(Foo)) or &__Foo
317*/
318#define CONSTRUCT_FROM_REFERENCE(class, constructor, context, ... )     \
319  ( (class)->constructor(                                               \
320                       (void *)_talloc_memdup(context, ((Object)class), ((Object)class)->__size,  __location__ "(" #class "." #constructor ")"), \
321                      ## __VA_ARGS__) )
322
323/** Finds the size of the class in x */
324#define CLASS_SIZE(class)                       \
325  ((Object)class)->__size
326
327typedef struct Object_t *Object;
328
329struct Object_t {
330  //A reference to a class instance - this is useful to be able to
331  //tell which class an object really belongs to:
332  Object __class__;
333
334  //And its super class:
335  Object __super__;
336
337  char *__name__;
338
339  /** Objects may have a doc string associated with them. */
340  char *__doc__;
341
342  //How large the class is:
343  int __size;
344};
345
346#define SUPER(base, imp, method, ...)            \
347  ((base)&__ ## imp)->method((base)self, ## __VA_ARGS__)
348
349#define GETCLASS(class)                         \
350  (Object)&__ ## class
351
352// Returns true if the obj belongs to the class
353#define ISINSTANCE(obj,class)                   \
354  (((Object)obj)->__class__ == GETCLASS(class))
355
356// This is a string comparison version of ISINSTANCE which works
357// across different shared objects.
358#define ISNAMEINSTANCE(obj, class)              \
359  (obj && !strcmp(class, NAMEOF(obj)))
360
361// We need to ensure that class was properly initialised:
362#define ISSUBCLASS(obj,class)                   \
363  issubclass((Object)obj, (Object)&__ ## class)
364
365#define CLASSOF(obj)                            \
366  ((Object)obj)->__class__
367
368void Object_init(Object);
369
370extern struct Object_t __Object;
371
372int issubclass(Object obj, Object class);
373
374extern void unimplemented(Object self);
375
376#define UNIMPLEMENTED(class, method)             \
377  ((class)self)->method = (void *)unimplemented;
378
379#define ZSTRING_NO_NULL(str) str , (strlen(str))
380#define ZSTRING(str) str , (strlen(str)+1)
381
382  // These dont do anything but are useful to indicate when a function
383  // parameter is used purely to return a value. They are now used to
384  // assist the python binding generator in generating the right sort
385  // of code
386#define OUT
387#define IN
388
389  // This modifier before a class means that the class is abstract and
390  // does not have an implementation - we do not generate bindings for
391  // that class then.
392#define ABSTRACT
393
394  // This modifier indicates that the following pointer is pointing to
395  // a borrowed reference - callers must not free the memory after use.
396#define BORROWED
397
398  // This tells the autobinder to generated bindings to this struct
399#define BOUND
400
401  // This tells the autobinder to ignore this class as it should be
402  // private to the implementation - external callers should not
403  // access this.
404#define PRIVATE
405
406  // This attribute of a method means that this method is a
407  // desctructor - the object is no longer valid after this method is
408  // run
409#define DESTRUCTOR
410
411  // including this after an argument definition will cause the
412  // autogenerator to assign default values to that parameter and make
413  // it optional
414#define DEFAULT(x)
415
416  // This explicitely denote that the type is a null terminated char
417  // ptr as opposed to a pointer to char and length.
418#define ZString char *
419
420  /* The following is a direction for the autogenerator to proxy the
421     given class. This is done in the following way:
422
4231) a new python type is created called Proxy_class_name() with a
424constructor which takes a surrogate object.
425
4262) The proxy class contains a member "base" of the type of the proxied
427C class.
428
4293) The returned python object may be passed to any C functions which
430expect the proxied class, and internal C calls will be converted to
431python method calls on the proxied object.
432  */
433#define PROXY_CLASS(name)
434
435  /* This signals the autogenerator to bind the named struct */
436#define BIND_STRUCT(name)
437
438  // This means that the memory owned by this pointer is managed
439  // externally (not using talloc). It is dangerous to use this
440  // keyword too much because we are unable to manage its memory
441  // appropriately and it can be free'd from under us.
442#define FOREIGN
443
444#endif
445#ifdef __cplusplus
446} /* closing brace for extern "C" */
447#endif
Note: See TracBrowser for help on using the repository browser.