| 1 | #include <stdio.h> |
| 2 | #include <malloc.h> |
| 3 | #include <assert.h> |
| 4 | |
| 5 | #define CONFEDERATION(IFACE,TYPE) struct IFACE *interface;struct TYPE *next |
| 6 | #define CREATE(TYPE) (struct TYPE *)malloc(sizeof(struct TYPE)) |
| 7 | #define APPEND(TYPE,MEMBER,LIST) (MEMBER?MEMBER->next=(struct TYPE *)LIST:0,LIST=(struct TYPE *)MEMBER) |
| 8 | #define SELF void *_self, void *_dummy |
| 9 | #define I_AM(TYPE) struct TYPE *self=(struct TYPE *)_self; |
| 10 | |
| 11 | struct Drawable_data |
| 12 | { |
| 13 | CONFEDERATION(Drawable_interface,Drawable_data); |
| 14 | }; |
| 15 | |
| 16 | struct Drawable_interface |
| 17 | { |
| 18 | void (*draw)(SELF); |
| 19 | int (*desc)(SELF, int something); |
| 20 | }; |
| 21 | |
| 22 | struct Tri |
| 23 | { |
| 24 | CONFEDERATION(Drawable_interface,Drawable_data); |
| 25 | int x1; int y1; int x2; int y2; int x3; int y3; |
| 26 | }; |
| 27 | |
| 28 | struct Rect |
| 29 | { |
| 30 | CONFEDERATION(Drawable_interface,Drawable_data); |
| 31 | int x1; int y1; int x2; int y2; |
| 32 | }; |
| 33 | |
| 34 | void draw_tri(SELF) |
| 35 | { |
| 36 | I_AM(Tri); |
| 37 | printf("imagine I am drawing %d,%d - %d,%d - %d,%d\n",self->x1,self->y1,self->x2,self->y2,self->x3,self->y3); |
| 38 | }; |
| 39 | |
| 40 | void draw_rect(SELF) |
| 41 | { |
| 42 | I_AM(Rect); |
| 43 | printf("imagine I am drawing %d,%d - %d,%d\n",self->x1,self->y1,self->x2,self->y2); |
| 44 | }; |
| 45 | |
| 46 | int desc_tri(SELF, int something) |
| 47 | { |
| 48 | I_AM(Tri); |
| 49 | printf("I am triangle %d,%d - %d,%d - %d,%d, method draw called with argument: %d\n",self->x1,self->y1,self->x2,self->y2,self->x3,self->y3, something); |
| 50 | return something; |
| 51 | }; |
| 52 | |
| 53 | int desc_rect(SELF, int something) |
| 54 | { |
| 55 | I_AM(Rect); |
| 56 | printf("I am rectangle %d,%d - %d,%d, method draw called with argument: %d\n",self->x1,self->y1,self->x2,self->y2, something); |
| 57 | return something; |
| 58 | }; |
| 59 | |
| 60 | struct Drawable_interface *init_tri_interface(void) |
| 61 | { |
| 62 | struct Drawable_interface *i=CREATE(Drawable_interface); |
| 63 | /* vsechny metody je bohuzel potreba bindnout rucne, neda se svitit... */ |
| 64 | if(i) { i->draw=draw_tri; i->desc=desc_tri; } |
| 65 | return i; |
| 66 | } |
| 67 | |
| 68 | struct Drawable_interface *init_rect_interface(void) |
| 69 | { |
| 70 | struct Drawable_interface *i=CREATE(Drawable_interface); |
| 71 | /* vsechny metody je bohuzel potreba bindnout rucne, neda se svitit... */ |
| 72 | if(i) { i->draw=draw_rect; i->desc=desc_rect; } |
| 73 | return i; |
| 74 | } |
| 75 | |
| 76 | struct Tri *create_tri(struct Drawable_interface *i, int x1, int y1, int x2, int y2, int x3, int y3) |
| 77 | { |
| 78 | struct Tri *t=CREATE(Tri); |
| 79 | if(i && t) |
| 80 | { |
| 81 | t->interface=i; |
| 82 | t->x1=x1;t->y1=y1;t->x2=x2;t->y2=y2;t->x3=x3;t->y3=y3; |
| 83 | } |
| 84 | return t; |
| 85 | } |
| 86 | |
| 87 | struct Rect *create_rect(struct Drawable_interface *i, int x1, int y1, int x2, int y2) |
| 88 | { |
| 89 | struct Rect *r=CREATE(Rect); |
| 90 | if(i && r) |
| 91 | { |
| 92 | r->interface=i; |
| 93 | r->x1=x1;r->y1=y1;r->x2=x2;r->y2=y2; |
| 94 | } |
| 95 | return r; |
| 96 | } |
| 97 | |
| 98 | int main(void) |
| 99 | { |
| 100 | struct Drawable_interface *tri_interface=init_tri_interface(); |
| 101 | struct Drawable_interface *rect_interface=init_rect_interface(); |
| 102 | struct Drawable_data *all=NULL,*one; |
| 103 | struct Tri *t; |
| 104 | struct Rect *r; |
| 105 | |
| 106 | r=create_rect(rect_interface,0,10,1,11); |
| 107 | APPEND(Drawable_data,r,all); |
| 108 | t=create_tri(tri_interface,0,0,0,4,3,0); |
| 109 | APPEND(Drawable_data,t,all); |
| 110 | r=create_rect(rect_interface,10,0,11,1); |
| 111 | APPEND(Drawable_data,r,all); |
| 112 | |
| 113 | /* a nyni ... bylo to hodne prace, ale povedlo se ... ! */ |
| 114 | |
| 115 | for(one=all;one;one=one->next) |
| 116 | { |
| 117 | printf("(return value %d)\n",(*(one->interface->desc)) (one,NULL,0)); |
| 118 | (*(one->interface->draw)) (one,NULL); |
| 119 | } |
| 120 | |
| 121 | /* ...a nakonec pro efekt jeste instatni nudlovy kod s kanci prichuti dle ANSI C99: */ |
| 122 | |
| 123 | #define _ARG1(ARG1,...) ARG1 |
| 124 | #define _(OBJECT,...) (assert(OBJECT),/**/(*(OBJECT->interface->_ARG1(__VA_ARGS__,)))/**/(OBJECT,OBJECT->interface->__VA_ARGS__)/**/) |
| 125 | #define FOR_EACH(ONE,ALL) for(ONE=ALL;ONE;ONE=ONE->next) |
| 126 | |
| 127 | FOR_EACH(one,all) |
| 128 | { |
| 129 | printf("(return value %d)\n",_(one,desc,1)); |
| 130 | _(one,draw); |
| 131 | } |
| 132 | |
| 133 | return 0; |
| 134 | } |