A
Arnaud Legrand
Hello,
I have a question about portability and I have not found the answer in the
FAQ. I have different modules to build. All of them have the same private
part and a common public part (though the implementation in all cases may be
different). Note that I already have implemented a similar idea and that it
works pretty well with my gcc but I don't know whether it is portable or not
(especially with those damn padding bytes... . As a tiny example is better
than a long explanation let me explain you how I actually write it (this is
a brain dead example but it is to explain the idea):
#define PUBLIC \
int (*get)(void* self); \
void (*reset)(void* self)
#define EXTENSION_PLUS \
void (*inc)(void *self); \
void (*dec)(void *self)
#define EXTENSION_TIMES \
void(*double)(void *self); \
void(*divide_by_two)(void *self) \
I know these defines are ugly. That is one of the other reason why I'm
asking beside portability.
With these macros, I can define two different modules with the following
API:
typedef struct {
PUBLIC;
EXTENSION_PLUS;
} s_counter_t, *counter_t;
counter_t counter_new(void);
void counter_free(counter_t c);
and
typedef struct {
PUBLIC;
EXTENSION_TIME;
} s_exponent_t, *exponent_t;
exponent_t exponent_new(void);
void exponent_free(exponent_t e);
In fact, both implementation of these modules include the following common
definition:
#define PRIVATE \
int value
typedef struct {
PRIVATE;
} s_private_common_part_t, *private_common_part_t;
In counter.c, one would find
typedef struct {
PRIVATE;
PUBLIC;
EXTENSION_PLUS;
} s_private_counter_t, *private_counter_t;
counter_new() actually creates a private_counter_t
-------------------------------------
| PRIVATE | PUBLIC | EXTENSION_PLUS |
-------------------------------------
^
|_________
but returns a pointer to here |, i.e. a valid counter_t.
Likewise, in exponent.c, one would find:
typedef struct {
PRIVATE;
PUBLIC;
EXTENSION_TIMES;
} s_private_exponent_t, *private_exponent_t;
exponent_new() would actually creates a private_exponent_t
--------------------------------------
| PRIVATE | PUBLIC | EXTENSION_TIMES |
--------------------------------------
Both module access their PRIVATE values by accessing memory a little bit
before their argument. The nice point with such a way of defining these
modules is that you can then use them seamlessly like that :
counter = counter_new();
exponent = exponent_new();
counter->reset(counter); /* set to 0 */
counter->inc(counter); /* ++ */
counter->get(counter); /* returns 1 */
exponent->reset(exponent); /* set to 1 */
exponent->double(exponent); /* *=2 */
exponent->get(exponent); /* returns 2 */
In this example you always have to give exponent as an argument but in my
particular case, there is always a unique object for each module (at most
one counter and one exponent) and the arguments are generally some other
abstract datatypes (void * is the correct C word for polymorphism, right?.
OK. Now that I have proved you that I knew how to write something ugly, let
me precise that before writing it like that, I were using struct definitions
instead of these #define. But I had to write :
exponent->public.reset(); /* set to 1 */
exponent->extension.double(); /* *=2 */
exponent->public.get(); /* returns 2 */
Even though the version with whole structures is cleaner and definitely
portable, I think that the one I have just written is really convenient for
users (no need to wonder whether you are using a basic functionality or a
extension).
Thanks for reading until here. Any suggestion ?
Arnaud
I have a question about portability and I have not found the answer in the
FAQ. I have different modules to build. All of them have the same private
part and a common public part (though the implementation in all cases may be
different). Note that I already have implemented a similar idea and that it
works pretty well with my gcc but I don't know whether it is portable or not
(especially with those damn padding bytes... . As a tiny example is better
than a long explanation let me explain you how I actually write it (this is
a brain dead example but it is to explain the idea):
#define PUBLIC \
int (*get)(void* self); \
void (*reset)(void* self)
#define EXTENSION_PLUS \
void (*inc)(void *self); \
void (*dec)(void *self)
#define EXTENSION_TIMES \
void(*double)(void *self); \
void(*divide_by_two)(void *self) \
I know these defines are ugly. That is one of the other reason why I'm
asking beside portability.
With these macros, I can define two different modules with the following
API:
typedef struct {
PUBLIC;
EXTENSION_PLUS;
} s_counter_t, *counter_t;
counter_t counter_new(void);
void counter_free(counter_t c);
and
typedef struct {
PUBLIC;
EXTENSION_TIME;
} s_exponent_t, *exponent_t;
exponent_t exponent_new(void);
void exponent_free(exponent_t e);
In fact, both implementation of these modules include the following common
definition:
#define PRIVATE \
int value
typedef struct {
PRIVATE;
} s_private_common_part_t, *private_common_part_t;
In counter.c, one would find
typedef struct {
PRIVATE;
PUBLIC;
EXTENSION_PLUS;
} s_private_counter_t, *private_counter_t;
counter_new() actually creates a private_counter_t
-------------------------------------
| PRIVATE | PUBLIC | EXTENSION_PLUS |
-------------------------------------
^
|_________
but returns a pointer to here |, i.e. a valid counter_t.
Likewise, in exponent.c, one would find:
typedef struct {
PRIVATE;
PUBLIC;
EXTENSION_TIMES;
} s_private_exponent_t, *private_exponent_t;
exponent_new() would actually creates a private_exponent_t
--------------------------------------
| PRIVATE | PUBLIC | EXTENSION_TIMES |
--------------------------------------
Both module access their PRIVATE values by accessing memory a little bit
before their argument. The nice point with such a way of defining these
modules is that you can then use them seamlessly like that :
counter = counter_new();
exponent = exponent_new();
counter->reset(counter); /* set to 0 */
counter->inc(counter); /* ++ */
counter->get(counter); /* returns 1 */
exponent->reset(exponent); /* set to 1 */
exponent->double(exponent); /* *=2 */
exponent->get(exponent); /* returns 2 */
In this example you always have to give exponent as an argument but in my
particular case, there is always a unique object for each module (at most
one counter and one exponent) and the arguments are generally some other
abstract datatypes (void * is the correct C word for polymorphism, right?.
OK. Now that I have proved you that I knew how to write something ugly, let
me precise that before writing it like that, I were using struct definitions
instead of these #define. But I had to write :
exponent->public.reset(); /* set to 1 */
exponent->extension.double(); /* *=2 */
exponent->public.get(); /* returns 2 */
Even though the version with whole structures is cleaner and definitely
portable, I think that the one I have just written is really convenient for
users (no need to wonder whether you are using a basic functionality or a
extension).
Thanks for reading until here. Any suggestion ?
Arnaud