By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,950 Members | 989 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,950 IT Pros & Developers. It's quick & easy.

Very Simple, Minimalist Technique For OOP in C...

P: n/a
Here is the example code:

- http://appcore.home.comcast.net/vzoo.../interface.zip
which is an analog of the following technique:

- http://groups.google.com/group/comp....f857051ca4029b
It's definitely not full-blown OOP is any sense of the term, however imho, I
think it could be fairly useful in certain scenarios... Now, let me try to
briefly describe it:

The provided example shows how a minimalist abstract interface for a "shape"
object might look. It also includes an implementation of simple circle and
square objects that are compatible with the abstract shape interface. If you
want to try and add another shape to get a feel for how "cumbersome" the
interface method is, well, here is a quick example of that:
<pseudo-code for adding, lets say, a triangle>
__________________________

triangle.h
__________________
/* Put include guard here */

#include "ishape.h"

/* Return values that are non-zero indicate error's */

/* Create a new triangle */
extern int Triangle_Create(IShape_t* const, /* [triangle params] */);

triangle.c
__________________
#include "triangle.h"
typedef struct Triangle_s Triangle_t;

struct Triangle_s {
/* [triangle members] */
};
static int Triangle_IObject_Destroy(void* const);
static int Triangle_IObject_Status(void* const);
static int Triangle_IShape_Draw(void* const);
/* Triangle IShape Interface VTable */
static IShape_VTable_t const Triangle_IShape_VTable = {
Triangle_IObject_Destroy,
Triangle_IObject_Status,
Triangle_IShape_Draw
};
/* Triangle Interface Functions */
int
Triangle_Create(
IShape_t* const IThis,
/* [triangle params] */) {
Triangle_t* const This = malloc(sizeof(*This));
if (This) {
/* [init This triangle] */
IOBJECT_INIT(IThis, This, &Triangle_IShape_VTable);
return 0;
}
return -1;
}
/* Triangle IObject Interface Functions */
int
Triangle_IObject_Destroy(void* const ThisState) {
Triangle_t* const This = ThisState;
free(This);
return 0;
}
int
Triangle_IObject_Status(void* const ThisState) {
Triangle_t* const This = ThisState;
/* [determine This triangle state; this is optional] */
return 0;
}
/* Triangle IShape Interface Functions */
int
Triangle_IShape_Draw(void* const ThisState) {
Triangle_t* const This = ThisState;
/* [draw This triangle] */
return 0;
}
__________________________


IMHO, that should be "fairly" straight forward... Now, here is how you could
use your Triangle:
__________________________

#include "triangle.h"

int Example(void) {
IShape_t MyShape;

int rStatus = Triangle_Create(&MyShape, /* [triangle params] */);
if (! rStatus) {

rStatus = IShape_Draw(&MyShape);
if (rStatus) {

rStatus = IObject_Status(&MyShape);
}

rStatus = IObject_Destroy(&MyShape);
}

return rStatus;
}
__________________________
I was wondering if you have come across any superior methods for very basic
OOP in C?
Any thoughts? Is this method total crap?

;^)
Thanks.

Jun 21 '07 #1
Share this Question
Share on Google+
10 Replies


P: n/a
"Chris Thomasson" <cr*****@comcast.netwrote in message
news:h_******************************@comcast.com. ..
[...]
It's definitely not full-blown OOP is any sense of the term, however imho,
I think it could be fairly useful in certain scenarios... Now, let me try
to briefly describe it:
[...]

Actually, I think the example code should be fairly self-explanatory...
Jun 21 '07 #2

P: n/a
"Chris Thomasson" <cr*****@comcast.netwrote in message
news:h_******************************@comcast.com. ..
Here is the example code:

- http://appcore.home.comcast.net/vzoo.../interface.zip
which is an analog of the following technique:

- http://groups.google.com/group/comp....f857051ca4029b
It's definitely not full-blown OOP is any sense of the term, however imho,
I think it could be fairly useful in certain scenarios...
[...]

I just remembered that a library called Nobel uses same basic technique:
You can create an abstract interface in C by declaring a vtable structure
and the interface structure self. First we setup a type for the VTable's
first parameter (e.g., 'this' in c++):
_______________
typedef void* IObject_This_t;
typedef IObject_This_t const VTable_This_t;
_______________


Now, lets say that our new interface will be for a thread/process
mutual-exclusion synchronization object. So, we need to declare the
following structs:
_______________
typedef struct IMutex_s IMutex_t;
typedef struct IMutex_VTable_s IMutex_VTable_t;
_______________

And then we define the struct for our mutex interface:
_______________
struct IMutex_s {
IObject_This_t This;
IMutex_VTable_t const *VTable;
};

/*Take note of the names of the members of IMutex_t: (This, VTable). Its
import that you keep the names you choose consistent because they are going
to be depended upon. More on that later.
*/
_______________


An abstract mutex interface needs at least the following abstract functions
(Destroy, Lock, Unlock), so we define the following vtable struct:
_______________
struct IMutex_VTable_s {
int (*fp_IObject_Destroy) (VTable_This_t);
int (*fp_Lock) (VTable_This_t);
int (*fp_Unlock) (VTable_This_t);

/*Take note of the names of the members of IMutex_VTable_t:
(fp_IObject_Destroy, fp_Lock, fp_Unlock). Its import that you keep the names
you choose consistent because they are going to be depended upon. More on
that later.
*/
};
_______________


Now, we need to define the abstract interface that makes use of all the
above. We start be defining a helper function and an abstract function that
can init/destroy any object:
_______________
#define IObject_Initialize(__IThis, __ThisPtr, __VTablePtr) \
(__IThis)->This = (__ThisPtr); \
(__IThis)->VTable = (__VTablePtr)

#define IObject_Destroy(__IThis) \
(__IThis)->VTable->fp_IObject_Destroy((__IThis)->This)
_______________

Now we define the abstract functions of IMutex_t:
_______________
#define IMutex_Lock(__IThis) \
(__IThis)->VTable->fp_Lock((__IThis)->This)

#define IMutex_Unlock(__IThis) \
(__IThis)->VTable->fp_Unlock((__IThis)->This)
_______________


Stick all the above in a header file called (imutex.h) or whatever and
that's it for the abstract interface part. Now you create an object that
makes use of the interface:
your_mutex.h
_______________
/* include guard */
#include "imutex.h"
extern int Your_Mutex_Create(IMutex_t* const);

your_mutex.c
_______________
#include "your_mutex.h"
#include <stdlib.h/* malloc/free */
/* declare/define your mutexs impl struct */
typedef struct Your_Mutex_s Your_Mutex_t;
typedef Your_Mutex_t* const Your_Mutex_This_t;

struct Your_Mutex_s {
/* [impl specific mutex data] */
};
/* declare your mutexs interface functions */
static int Your_Mutex_IObject_Destroy(VTable_This_t);
static int Your_Mutex_Lock(VTable_This_t);
static int Your_Mutex_Unlock(VTable_This_t);
/* define your mutex interface vtable */
static IMutex_VTable_t const Your_Mutex_VTable = {
Your_Mutex_IObject_Destroy,
Your_Mutex_Lock,
Your_Mutex_Unlock
};
/* define mutex create function */
int Your_Mutex_Create(IMutex_t* const IThis) {
Your_Mutex_This_t This = malloc(sizeof(*This));
if (This) {
/* [init impl This specific mutex data] */

/* init the IThis interface */
IObject_Initialize(IThis, This, &Your_Mutex_VTable);
return 0;
}
return -1;
}
/* define mutex object destroy */
int Your_Mutex_IObject_Destroy(VTable_This_t ThisState) {
Your_Mutex_This_t This = ThisState;
/* [teardown impl This specific mutex data] */
free(This);
return -1;
}
/* define mutex interface */
int Your_Mutex_Lock(VTable_This_t ThisState) {
Your_Mutex_This_t This = ThisState;
/* [lock impl This specific mutex] */
return -1;
}
int Your_Mutex_Unlock(VTable_This_t ThisState) {
Your_Mutex_This_t This = ThisState;
/* [unlock impl This specific mutex] */
return -1;
}
_______________
That's it for the interface and impl... Now you can use it like:
_______________
#include "your_mutex.h"
int Locked_Callback(
IMutex_t* const IThis,
int (*fp_Callback) (void*, IMutex* const),
void *CallbackState) {

int rStatus = IMutex_Lock(IThis);
if (! rStatus) {

rStatus = fp_Callback(CallbackState, IThis);
if (! rStatus) {
rStatus = IMutex_Unlock(IThis);
}
}

return rStatus;
}

static IMutex_t The_Lock;
int Critical_Section(void *ThisState, IMutex_t* const Lock) {
/* [your in a critical-section locked by 'Lock'] */
return 0;
}
void Some_Threads(/* [...] */) {
/* [...] */
Locked_Callback(&The_Lock, Critical_Section, /* [ptr to state */);
}
int main(void) {
int rStatus = Your_Mutex_Create(&The_Lock);
if (! rStatus) {
/* [create Some_Threads] */
}
return rStatus ;
}
_______________

Well, barring any typos, that's about it. ;^)
Jun 21 '07 #3

P: n/a
int main(void) {
int rStatus = Your_Mutex_Create(&The_Lock);
if (! rStatus) {
/* [create Some_Threads] */
/* [join threads] */

rStatus = IObject_Destroy(&The_Lock);
}
return rStatus ;
}
_______________

Jun 21 '07 #4

P: n/a
On Jun 21, 5:30 am, "Chris Thomasson" <cris...@comcast.netwrote:
Here is the example code:

-http://appcore.home.comcast.net/vzoom/example/interface.zip

which is an analog of the following technique:

-http://groups.google.com/group/comp.lang.c/msg/6cf857051ca4029b

It's definitely not full-blown OOP is any sense of the term, however imho, I
think it could be fairly useful in certain scenarios... Now, let me try to
briefly describe it:

The provided example shows how a minimalist abstract interface for a "shape"
object might look. It also includes an implementation of simple circle and
square objects that are compatible with the abstract shape interface. If you
want to try and add another shape to get a feel for how "cumbersome" the
interface method is, well, here is a quick example of that:

<pseudo-code for adding, lets say, a triangle>
__________________________

triangle.h
__________________
/* Put include guard here */

#include "ishape.h"

/* Return values that are non-zero indicate error's */

/* Create a new triangle */
extern int Triangle_Create(IShape_t* const, /* [triangle params] */);

triangle.c
__________________
#include "triangle.h"

typedef struct Triangle_s Triangle_t;

struct Triangle_s {
/* [triangle members] */

};

static int Triangle_IObject_Destroy(void* const);
static int Triangle_IObject_Status(void* const);
static int Triangle_IShape_Draw(void* const);

/* Triangle IShape Interface VTable */
static IShape_VTable_t const Triangle_IShape_VTable = {
Triangle_IObject_Destroy,
Triangle_IObject_Status,
Triangle_IShape_Draw

};

/* Triangle Interface Functions */
int
Triangle_Create(
IShape_t* const IThis,
/* [triangle params] */) {
Triangle_t* const This = malloc(sizeof(*This));
if (This) {
/* [init This triangle] */
IOBJECT_INIT(IThis, This, &Triangle_IShape_VTable);
return 0;
}
return -1;

}

/* Triangle IObject Interface Functions */
int
Triangle_IObject_Destroy(void* const ThisState) {
Triangle_t* const This = ThisState;
free(This);
return 0;

}

int
Triangle_IObject_Status(void* const ThisState) {
Triangle_t* const This = ThisState;
/* [determine This triangle state; this is optional] */
return 0;

}

/* Triangle IShape Interface Functions */
int
Triangle_IShape_Draw(void* const ThisState) {
Triangle_t* const This = ThisState;
/* [draw This triangle] */
return 0;}

__________________________

IMHO, that should be "fairly" straight forward... Now, here is how you could
use your Triangle:
__________________________

#include "triangle.h"

int Example(void) {
IShape_t MyShape;

int rStatus = Triangle_Create(&MyShape, /* [triangle params] */);
if (! rStatus) {

rStatus = IShape_Draw(&MyShape);
if (rStatus) {

rStatus = IObject_Status(&MyShape);
}

rStatus = IObject_Destroy(&MyShape);
}

return rStatus;}

__________________________

I was wondering if you have come across any superior methods for very basic
OOP in C?

Any thoughts? Is this method total crap?

;^)

Thanks.
The following article also covers OO programming in C:
http://www.eventhelix.com/RealtimeMa...mming_in_c.htm

--
EventStudio 4.0 - http://www.EventHelix.com/EventStudio
Sequence Diagram based System Modeling Tool

Jun 22 '07 #5

P: n/a

"Chris Thomasson" <cr*****@comcast.netwrote in message
news:h_******************************@comcast.com. ..
I was wondering if you have come across any superior methods for very
basic OOP in C?
typedef struct object
{
void *ptr;
void *(*query)(struct object *obj, char *interface);
void (*kill)(struct object *obj)
} OBJECT;

Every object you query for an interface. An example would be

typedef struct
{
double (*length)(OBJECT *obj);
int (*getpos)(OBJECT *obj, double t, double *x, double *y);
} LINE;

So we are passed a line

void drawline(OBJECT *obj)
{
LINE *line;
int len;
int i;

line = obj->query(obj, "line");
if(!line)
fprintf(stderr, "Must be passed a line\n"):
len = (int) line->length(obj) + 1;
for(i=0;i<len;i++)
{
line->getpos(obj, ((double)i)/len, &x, &y);
drawpixel(x, y);
}
}

However it really is a lot of trouble. The syntactical support isn't really
there, so code quickly becomes a complete mess.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Jun 22 '07 #6

P: n/a
On Thu, 21 Jun 2007 19:52:19 -0700, "EventHelix.com"
<ev********@gmail.comwrote:
snip
>
The following article also covers OO programming in C:
http://www.eventhelix.com/RealtimeMa...mming_in_c.htm
Did you really need to quote 130+ lines just to provide a reference.
Remove del for email
Jun 22 '07 #7

P: n/a
Barry Schwarz <sc******@doezl.netwrote:
On Thu, 21 Jun 2007 19:52:19 -0700, "EventSpam.com"
<ev*******@gmail.comwrote:
The following article also covers OO programming in C:
http://www.eventspam.com/spam.htm

Did you really need to quote 130+ lines just to provide a reference.
No; but did you really need to quote a known spammer without munging his
links?

Richard
Jun 22 '07 #8

P: n/a
On Fri, 22 Jun 2007 10:39:10 GMT, rl*@hoekstra-uitgeverij.nl (Richard
Bos) wrote:

>
No; but did you really need to quote a known spammer without munging his
links?
He's not one of the spammers I recognized and the link actually
contained reasonable C code.
Remove del for email
Jun 22 '07 #9

P: n/a
"Malcolm McLean" <re*******@btinternet.comwrote in message
news:kZ*********************@bt.com...
>
"Chris Thomasson" <cr*****@comcast.netwrote in message
news:h_******************************@comcast.com. ..
>I was wondering if you have come across any superior methods for very
basic OOP in C?
[...]
However it really is a lot of trouble. The syntactical support isn't
really there, so code quickly becomes a complete mess.
Yeah, that seems to attempt to support more OOP techniques than the
"minimalist" method posted, which only provides an abstract interface
technique.

Jun 24 '07 #10

P: n/a
Chris Thomasson wrote:
"Malcolm McLean" <re*******@btinternet.comwrote in message
news:kZ*********************@bt.com...
>>
"Chris Thomasson" <cr*****@comcast.netwrote in message
news:h_******************************@comcast.com ...
>>I was wondering if you have come across any superior methods for very
basic OOP in C?
[...]
>However it really is a lot of trouble. The syntactical support isn't
really there, so code quickly becomes a complete mess.

Yeah, that seems to attempt to support more OOP techniques than the
"minimalist" method posted, which only provides an abstract interface
technique.
You are right, the syntactical support isn't really there, but it is
quite possible to do full OOP in C with virtual functions and
everything, and it isn't that hard to do really.
It is even possible to do it better than in C++ with respect to using an
object oriented plugin system, something not easily done in C++, at
least not if you are *not* interested in recompiling every plugin at any
change in some of the base classes. I do not know about C# or other
languages - it might be better solved there but C is somewhat easier
because everything becomes visible and that makes it easier to see the
limitations and understand what happens. (I have done two
implementations of plugin based object oriented systems, one in C++ and
later one in C, the one in C actually meets the specifications better
even if it is more lines of code to do the work).
Jun 24 '07 #11

This discussion thread is closed

Replies have been disabled for this discussion.