Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

A novel approach to creating templates in C

350 views
Skip to first unread message

usene...@yahoo.com

unread,
Jun 7, 2009, 4:26:10 PM6/7/09
to
Toward the end of the page:
http://home.comcast.net/~fbui/OOC.html

Chris M. Thomasson

unread,
Jun 7, 2009, 9:28:31 PM6/7/09
to
<usene...@yahoo.com> wrote in message
news:3d58fb2a-7bf7-45ce...@u10g2000vbd.googlegroups.com...

> Toward the end of the page:
> http://home.comcast.net/~fbui/OOC.html

Why are you actually putting interface function-pointers within the struct
itself? IMVHO, this can be a huge waste of space. A MUCH more space
efficient approach is to include a single pointer to a constant vtable.
Something like this, modulo bugs because I am quickly typing it directly in
the newsreader:


/* common object private vtable */
struct object_prv_vtable {
int (*fp_destroy) (void* const);
};

/* common object interface */
#define object_destroy(t) ( \
(t)->vtable->object.fp_destroy((t)) \
)


/* common device private vtable */
#include <stddef.h>


struct device_prv_vtable {
int (*fp_read) (void* const, void*, size_t);
int (*fp_write) (void* const, void const*, size_t);
};


/* common device vtable */
struct device_vtable {
struct object_prv_vtable const object;
struct device_prv_vtable const device;
};


/* common device object */
struct device {
struct device_vtable const* vtable;
};


/* common device interface */
#define device_read(t, b, s) ( \
(t)->vtable->device.fp_read((t), (b), (s)) \
)

#define device_write(t, b, s) ( \
(t)->vtable->device.fp_write((t), (b), (s)) \
)


There. That's all the scaffolding we need. Now its time to show a concrete
implementation of a device. Lets call the device a `usb_drive'. Here is the
header file:

/* usb_drive.h */
#if ! defined (USB_DRIVE_H)
#define USB_DRIVE_H

extern int usb_drive_create(struct device**);

#endif

Okay, here is the implementation file:

/* usb_drive.c */
#include "usb_drive.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>


struct usb_drive {
struct device device;
/* whatever */
};


static int object_destroy(void*);
static int device_read(void*, void*, size_t);
static int device_write(void*, void const*, size_t);


static struct device_vtable const g_vtable[
{ /* object interface */
object_destroy
},

{ /* device interface */
device_read,
device_write
}
];


int usb_drive_create(
struct device** pself
) {
struct usb_drive* const self = malloc(sizeof(*self));
if (self) {
*pself = &self->device;
return 0;
}
return ENOMEM;
}


int object_destroy(void* const self_) {
struct usb_drive* const self = self_;
free(self);
printf("destroyed a usb_drive(%p)\n", self_);
return 0;
}


int device_read(void* const self_, void* buf, size_t size) {
struct usb_drive* const self = self_;
printf("read from a usb_drive(%p, %p, %lu)\n",
self_, buf, (unsigned long) size);
return 0;
}


int device_read(void* const self_, void* buf, size_t size) {
struct usb_drive* const self = self_;
printf("wrote to a usb_drive(%p, %p, %lu)\n",
self_, buf, (unsigned long) size);
return 0;
}


Well, now its time to actually use it:


#include <usb_drive.h>


void read_write(
struct device* const self
) {
char buf[100];

device_read(a_device, buf, 50);

device_write(a_device, buf, 5);
}


int main(void) {
struct device* a_device;

if (! usb_drive_create(&a_device)) {
read_write(a_device);

object_destroy(a_device);
}

return 0;
}

There, that is an example of a minimalist abstract interface technique in C.

Any thoughts?

Chris M. Thomasson

unread,
Jun 7, 2009, 9:35:59 PM6/7/09
to
<usene...@yahoo.com> wrote in message
news:3d58fb2a-7bf7-45ce...@u10g2000vbd.googlegroups.com...
> Toward the end of the page:
> http://home.comcast.net/~fbui/OOC.html

I seem to remember an old header file that was in some, UNIX I think?,
distributions that implemented the same thing. I cannot remember the name of
the header. Perhaps somebody can refresh my memory.

Chris M. Thomasson

unread,
Jun 8, 2009, 12:21:54 AM6/8/09
to

"Chris M. Thomasson" <n...@spam.invalid> wrote in message
news:VOZWl.6969$v24....@newsfe13.iad...
> <usene...@yahoo.com> wrote in message [...] Okay, here is the


Ummmm, well, I should go ahead and point the device object to the fuc%ing
VTABLE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! OUCH!!!!


self->device.vtable = &g_vtable;


> return 0;
> }
> return ENOMEM;
> }
>
>
> int object_destroy(void* const self_) {
> struct usb_drive* const self = self_;
> free(self);
> printf("destroyed a usb_drive(%p)\n", self_);
> return 0;
> }
>
>
> int device_read(void* const self_, void* buf, size_t size) {
> struct usb_drive* const self = self_;
> printf("read from a usb_drive(%p, %p, %lu)\n",
> self_, buf, (unsigned long) size);
> return 0;
> }
>
>
> int device_read(void* const self_, void* buf, size_t size) {
> struct usb_drive* const self = self_;
> printf("wrote to a usb_drive(%p, %p, %lu)\n",
> self_, buf, (unsigned long) size);
> return 0;
> }

> [...]

Chris M. Thomasson

unread,
Jun 8, 2009, 12:41:43 AM6/8/09
to
"Chris M. Thomasson" <n...@spam.invalid> wrote in message
news:VOZWl.6969$v24....@newsfe13.iad...
> <usene...@yahoo.com> wrote in message
> news:3d58fb2a-7bf7-45ce...@u10g2000vbd.googlegroups.com...
>> Toward the end of the page:
>> http://home.comcast.net/~fbui/OOC.html
>
> Why are you actually putting interface function-pointers within the struct
> itself? IMVHO, this can be a huge waste of space. A MUCH more space
> efficient approach is to include a single pointer to a constant vtable.
> Something like this, modulo bugs because I am quickly typing it directly
> in the newsreader:
> [...]


Here ya go:


http://clc.pastebin.com/f52a443b1


fully compliable code.

blargg

unread,
Jun 8, 2009, 9:02:42 AM6/8/09
to
usene...@yahoo.com wrote:
> A novel approach to creating templates in C Toward the end of the page:
> http://home.comcast.net/~fbui/OOC.html

C++ used a scheme like this before it had templates:

http://h30097.www3.hp.com/cplus/6026pro_genr.html

http://www.softwarepreservation.org/projects/c_plus_plus/cfront/release_3.0.3/source/incl-master/const-headers/generic.h/view

BTW, please use the message subject to summarize the body, not as the
first few words of the message body; the body should stand on its own.

Chris M. Thomasson

unread,
Jun 11, 2009, 3:35:57 AM6/11/09
to
"blargg" <blarg...@gishpuppy.com> wrote in message
news:blargg.ei3-08...@192.168.1.4...

Bingo! `generic.h' was the EXACT header I was thinking of!


;^)


Thank you blargg; I was on the tip of my mind!

Ouch...

fft1976

unread,
Jul 1, 2009, 12:10:20 AM7/1/09
to
On Jun 7, 1:26 pm, usenetfu...@yahoo.com wrote:
> Toward the end of the page:http://home.comcast.net/~fbui/OOC.html

I think the approach A (templates via macros) is pretty good. I wonder
if there is already a ROBUST and consistent library of these, similar
to STL?

0 new messages