Hiya,
Terrible subject but I haven't got a better term at the moment.
I've been building up my own library of functionality (all nice conforming
ISO C) for over 6 years and decided to adopt a more OO approach to fit my
needs. Altough I used an OO approach previously for some subparts of the
library it became somewhat difficult to maintain all those parts since they
really are the same thing coded for each part (code duplication). So what I
am coding up is this: a binary tree which in each node contains 2 additional
binary trees, one for data and for functions (methods). Each 'class' defines
a couple of basic methods such as ctor() and dtor() (constructor,
destructor) and a clone() function. Data is nicely abstracted and has all
kinds of flags (hidden, protected, etc) and includes the size, offset in the
structure, additional help, default values, etc. Anyway, nothing new -
people already did this (see for example
http://www.planetpdf.com/mainpage.asp?WebPageID=620
for a nice introduction). So my classes can inherent each other, overload
functions, do some logic on given parameters, it can generate documentation
on it's self, build a gui framework from the parameters, etc. Essentially
your basic OO functionality wich is fairly fast (the tree helps a lot) and
forces me into modular thinking and gives me a flexible way to extend my
library in the future (essentially all algorithms are now in a 'plugin'
format and even dynamicly loaded objects are simple addition)
And now the problem ...
imagine I have a 'image' class - i.e. a class that allocated a bitmap/pixmap
object and return a pointer to that class:
void * image = new("image", 320, 200, 10);
the new() call will parse the parameters and convert them to variadic list
(e.g. the "image" object is found in the tree and ctor() is called with the
va_list) - this is nice since it allows me to use different parameters
depending on the type of object returned from the class.
The problem arises when I would want to call a get_pixel() routine. I could
code it up just as the new() call i.e. using variable argument lists. The
problem that this is way too slow for a function that is called a lot. I
timed it and wrote a little program to compare one getpixel() with variable
arguments and one with non-variable arguments (i.e. int get_pixel(void *
object, int x, int y)) and the va_list version was about twice as slow
(which is natural due to the overhead of the argument parsing of va_arg() in
the function)).
I guess there is no real solution to my problem (but I'm hoping some bright
mind has a good idea!) but what I would want is some way to abstract
functions while still be able to use them in a fast way. There are a couple
of solutions I thought up:
1. just create a function:
int get_pixel(void * object, int x, int y)
e.g.
void * image = new("image", 320, 200, 8);
int the_pixel = get_pixel(image, 100, 100);
Problem: This works but is not very nice from an API point of view. It is
not obvious that get_pixel() belongs to the image class. Of course if the
object is not of type 'image' the function will bail out but that is not
elegant enough for me. Essentially; there is no real relation between
get_pixel() and the image class (the image class doesn't know there is a
get_pixel)
2. create the variable argument list function - this means that *all*
functions (in the whole library which conform to this type of calling)
should be in the same format, say:
void * do_something(void * self, const char * what, va_list * args)
and I would call it (through a wrapper) something like:
do_something(image, "get_pixel", x, y, &result)
Problem: I guess this would work but as mentioned earlier this is way to
slow for functions that get called a lot. The nice things is that I can ask
the class what type of functions it has and therefore automagically create
documentation for each class which helps in preserving the API. Another nice
thing is that overloading these types of functions becomes easy.
Essentially; there now *is* a relation between the class and the function.
3. I could create some pointers to the 'x' and 'y' elements in the class
data structure and loop over them and call do_something(image, "get_pixel")
and retrieve the result with another pointer.
Problem: this is just way nasty - very error prone and it would mean I'd be
adjusting all my loops which would now use the pointer instead of just
integers - it would certainly become more unreadable and hard to change in
the future.
4. Use C++
C++ is not an option. it's a silly language IMHO (please: no flame war)
5. Maybe, just maybe it would be possible to generate a faster function when
needed ... ?
something like:
int (*func)(void * object, int x, int y) = generate_function(image,
"get_pixel");
and then just use func(), e.g.:
int the_pixel = func(image, 100, 100);
But I guess this can't be done (how in the hell should generate_function be
able to return a function that can contain any kind of parameters)
So this is where I'm stuck - I would really like to get some input on
this... maybe there is some way that I didn't think of that will give me an
elegant solution to the problem at hand. The solution should be portable (as
in ISO C89).
Any tips/hints welcome...
Cheers,
Gibby