Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > [Slightly OT] Trying to simulate OOP with C

Reply
Thread Tools

[Slightly OT] Trying to simulate OOP with C

 
 
Deniz Bahar
Guest
Posts: n/a
 
      02-20-2005
Hello,

A couple days ago my friend (OOP guy) shows me what OOP was all about
in C++. This morning I figured I can do pretty much the same thing
with C (by putting function pointers in structures and using Macros).

I've gone pretty far but I'm running into problems because the function
pointers within the structures need an extra argument (a pointer to
that type of structure) so they know which data to operate on. Also, I
have to initialize all the functions pointers for every structure
object I define.

I'm trying to get rid of all this using Macros, and this is where I
need help.
I get "invalid type argument ->" as error message from my
compiler/preprocessor.

Here are the includes and macros:
---------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define InitFunctions(P) {(P)->setname = nameset;
(P)->setlover = loverset;
(P)->setIQ = IQset;}

#define (P).NAME(S) (P).setname( (S), &(P) );

#define (P).LOVER(S, I) (P).setlover( (S), (I), &(P) );

#define (P).IQ(I) (P).setIQ( (I) , &(P) );



Here is my structure(simulated class) template:
-----------------------------------------------

struct PersonTag
{
char name[40];
char loves[20][40];
int IQ;


char *(*setname)(const char *, struct PersonTag *);
char *(*setlover)(const char *, int index, struct PersonTag *);
int (*setIQ)(const int, struct PersonTag *);

};
typedef struct PersonTag Person;



Here are the function definitions:
----------------------------------

char *nameset(const char *name, Person *P)
{
/* name = NULL signals read operation */
if(name)
strcpy(P->name, name);
return P->name;
}


char *loverset(const char *newlove, int index, Person *P)
{
/* newlove = NULL signals read operation */
if(newlove)
strcpy(P->loves[index], newlove);
return P->loves[index];
}


int IQset(const int IQ, Person *P)
{
/* IQ = 0 signals read operation */
if(IQ)
P->IQ = IQ;
return P->IQ;
}



Here is my main function:
-------------------------

int main(void)
{
Person Dan;
InitFunctions(Dan);

Dan.NAME("Dan");
Dan.LOVER("Julia", 0);
Dan.IQ(100);

printf("Name = %s\nFirst Lover = %s\n,IQ = %d\n",
Dan.NAME(NULL), Dan.LOVER(NULL,0), Dan.IQ(0) );

return 0;
}




I am not too worried about buffer overflow or error checking at this
point (strcpy). My difficulties are in trying to "hide away" the
operations of: setting function pointers in the structure objects to
the proper functions AND passing extra structure pointer argument every
time a function is called.

I would think this is possible because the name of the structure is
always used when I call a function, and it's seems pointless that I
keep having to repeat the name.

Examples:

Bob.setlover("Teresa" , &Bob);
Bob.setIQ(120, &Bob);

As you can see, "Bob" comes twice for each call. Can anyone help me
with my macros or point me to another solution? Thanks

 
Reply With Quote
 
 
 
 
Toni Uusitalo
Guest
Posts: n/a
 
      02-20-2005

"Deniz Bahar" <> wrote in message
news: oups.com...
> Hello,
>
> A couple days ago my friend (OOP guy) shows me what OOP was all about
> in C++. This morning I figured I can do pretty much the same thing
> with C (by putting function pointers in structures and using Macros).
>
> I've gone pretty far but I'm running into problems because the function
> pointers within the structures need an extra argument (a pointer to
> that type of structure) so they know which data to operate on. Also, I
> have to initialize all the functions pointers for every structure
> object I define.
>
> I'm trying to get rid of all this using Macros, and this is where I
> need help.
> I get "invalid type argument ->" as error message from my
> compiler/preprocessor.


Sorry in advance that I don't answer to the question about your error
message but
I only answer to the OOP question:

If you need true objects: Use C++ or perhaps Objective-C.

I personally think that careful OOP style naming (see for example GLIB -
something like
http://developer.gnome.org/doc/API/2...te-Arrays.html)
will be enough. No need for messy vtables etc.)

google for example for "object oriented vtable C". One hit:
http://www.embedded.com/97/fe29712.htm

with respect,
Toni Uusitalo


 
Reply With Quote
 
 
 
 
Michael Mair
Guest
Posts: n/a
 
      02-20-2005
Deniz Bahar wrote:
> Hello,
>
> A couple days ago my friend (OOP guy) shows me what OOP was all about
> in C++. This morning I figured I can do pretty much the same thing
> with C (by putting function pointers in structures and using Macros).


OO in C is not OT round here.

> I've gone pretty far but I'm running into problems because the function
> pointers within the structures need an extra argument (a pointer to
> that type of structure) so they know which data to operate on. Also, I
> have to initialize all the functions pointers for every structure
> object I define.


Hmmm, register new classes "somewhere" and give this somewhere only
a standard constructor which does only the setup of function pointers.
Then, CreateObject(ClassName) is all you have to work with.

In special cases, it might even make sense to have sample class objects
which get memcpy()ed to new class objects.

The problem with passing the address of the object calling a method
cannot be circumvented.

There was a discussion about OOP in C some time ago on c.l.c where
I was involved. Use groups.google.
There was also a book about object oriented programming in ANSI C
mentioned. I cannot say anything about its quality; google for ooc.pdf.

> I'm trying to get rid of all this using Macros, and this is where I
> need help.
> I get "invalid type argument ->" as error message from my
> compiler/preprocessor.
>
> Here are the includes and macros:
> ---------------------------------
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
> #define InitFunctions(P) {(P)->setname = nameset;
> (P)->setlover = loverset;
> (P)->setIQ = IQset;}


Look at the do {} while 0 construct in the c.l.c FAQ
>
> #define (P).NAME(S) (P).setname( (S), &(P) );
>
> #define (P).LOVER(S, I) (P).setlover( (S), (I), &(P) );
>
> #define (P).IQ(I) (P).setIQ( (I) , &(P) );


This is not C.
You cannot fake ::, so use standard C macros.

About the interface: What do all your calls have in common?
Exactly. &P gets passed. So make it the same position in
all calls, i.e. the first argument.


Cheers
Michael
>
> Here is my structure(simulated class) template:
> -----------------------------------------------
>
> struct PersonTag
> {
> char name[40];
> char loves[20][40];
> int IQ;
>
>
> char *(*setname)(const char *, struct PersonTag *);
> char *(*setlover)(const char *, int index, struct PersonTag *);
> int (*setIQ)(const int, struct PersonTag *);
>
> };
> typedef struct PersonTag Person;
>
>
>
> Here are the function definitions:
> ----------------------------------
>
> char *nameset(const char *name, Person *P)
> {
> /* name = NULL signals read operation */
> if(name)
> strcpy(P->name, name);
> return P->name;
> }
>
>
> char *loverset(const char *newlove, int index, Person *P)
> {
> /* newlove = NULL signals read operation */
> if(newlove)
> strcpy(P->loves[index], newlove);
> return P->loves[index];
> }
>
>
> int IQset(const int IQ, Person *P)
> {
> /* IQ = 0 signals read operation */
> if(IQ)
> P->IQ = IQ;
> return P->IQ;
> }
>
>
>
> Here is my main function:
> -------------------------
>
> int main(void)
> {
> Person Dan;
> InitFunctions(Dan);
>
> Dan.NAME("Dan");
> Dan.LOVER("Julia", 0);
> Dan.IQ(100);
>
> printf("Name = %s\nFirst Lover = %s\n,IQ = %d\n",
> Dan.NAME(NULL), Dan.LOVER(NULL,0), Dan.IQ(0) );
>
> return 0;
> }
>
>
>
>
> I am not too worried about buffer overflow or error checking at this
> point (strcpy). My difficulties are in trying to "hide away" the
> operations of: setting function pointers in the structure objects to
> the proper functions AND passing extra structure pointer argument every
> time a function is called.
>
> I would think this is possible because the name of the structure is
> always used when I call a function, and it's seems pointless that I
> keep having to repeat the name.
>
> Examples:
>
> Bob.setlover("Teresa" , &Bob);
> Bob.setIQ(120, &Bob);
>
> As you can see, "Bob" comes twice for each call. Can anyone help me
> with my macros or point me to another solution? Thanks
>



--
E-Mail: Mine is an /at/ gmx /dot/ de address.
 
Reply With Quote
 
Michael Mair
Guest
Posts: n/a
 
      02-20-2005
Michael Mair wrote:
>
> Look at the do {} while 0 construct in the c.l.c FAQ


Make that while (0); sorry.
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
 
Reply With Quote
 
E. Robert Tisdale
Guest
Posts: n/a
 
      02-21-2005
Deniz Bahar wrote:
>
>
> A couple days ago my friend (OOP guy) shows me what OOP was all about
> in C++. This morning I figured I can do pretty much the same thing
> with C (by putting function pointers in structures and using Macros).
>
> I've gone pretty far but I'm running into problems because the function
> pointers within the structures need an extra argument (a pointer to
> that type of structure) so they know which data to operate on. Also, I
> have to initialize all the functions pointers for every structure
> object I define.
>
> I'm trying to get rid of all this using Macros, and this is where I
> need help.
> I get "invalid type argument ->" as error message from my
> compiler/preprocessor.
>
> Here are the includes and macros:
> ---------------------------------
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
> #define InitFunctions(P) {(P)->setname = nameset;
> (P)->setlover = loverset;
> (P)->setIQ = IQset;}


This should be done by the [pseudo] constructor.
Ditch the macros. Use inline static functions instead.

> #define (P).NAME(S) (P).setname( (S), &(P) );
>
> #define (P).LOVER(S, I) (P).setlover( (S), (I), &(P) );
>
> #define (P).IQ(I) (P).setIQ( (I) , &(P) );


These aren't valid macro definitions.

> Here is my structure(simulated class) template:
> -----------------------------------------------
>
> struct PersonTag {
> char name[40];
> char loves[20][40];
> int IQ;
> char *(*setname)(const char *, struct PersonTag *);
> char *(*setlover)(const char *, int index, struct PersonTag *);
> int (*setIQ)(const int, struct PersonTag *);
>
> };
> typedef struct PersonTag Person;
>
> Here are the function definitions:
> ----------------------------------
>
> char *nameset(const char *name, Person *P) {
> /* name = NULL signals read operation */
> if(name)
> strcpy(P->name, name);
> return P->name;
> }
>
> char *loverset(const char *newlove, int index, Person *P) {
> /* newlove = NULL signals read operation */
> if(newlove)
> strcpy(P->loves[index], newlove);
> return P->loves[index];
> }
>
> int IQset(const int IQ, Person *P) {
> /* IQ = 0 signals read operation */
> if(IQ)
> P->IQ = IQ;
> return P->IQ;
> }
>
> Here is my main function:
> -------------------------
>
> int main(void) {
> Person Dan;
> InitFunctions(Dan);
>
> Dan.NAME("Dan");
> Dan.LOVER("Julia", 0);
> Dan.IQ(100);
>
> printf("Name = %s\nFirst Lover = %s\n,IQ = %d\n",
> Dan.NAME(NULL), Dan.LOVER(NULL,0), Dan.IQ(0) );
>
> return 0;
> }
>
> I am not too worried about
> buffer overflow or error checking at this oint (strcpy).
> pMy difficulties are in trying to "hide away" the operations of:
> setting function pointers in the structure objects to the proper functions
> AND passing extra structure pointer argument
> every time a function is called.
>
> I would think this is possible
> because the name of the structure is always used when I call a function,
> and it seems pointless that I keep having to repeat the name.
>
> Examples:
>
> Bob.setlover("Teresa" , &Bob);
> Bob.setIQ(120, &Bob);
>
> As you can see, "Bob" comes twice for each call.
> Can anyone help me with my macros or point me to another solution?


The member function pointers don't buy you anything
unless you want to implement [run-time] polymorphism.
The way this is done is to create a Virtual function TABLE (VTABLE)
which contains pointers to the [actual] functions
and include a pointer to this table in each object.
Virtual functions reference the actual functions
through the pointers in the VTABLE.

> cat main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define LENGTH 40
#define LOVERS 20
typedef struct Person {
const
void* pvft; // virtual function table pointer
char name[LENGTH];
size_t lovers;
char lover[LOVERS][LENGTH];
int IQ;
} Person;

typedef struct Person_virtualFunctionTable_t {
const char* (*name)(const Person*);
const char* (*love)(const Person*, size_t);
int (*IQ)(const Person*);
Person* (*newLove)(Person*, const char*);
int (*fprint)(FILE*, const Person*);
void (*destroy)(const Person*);
} Person_virtualFunctionTable_t;

const char*
ActualPerson_name(const Person* const p) {
return p->name;
}

const char*
ActualPerson_lover(const Person* const p, size_t lover) {
return (lover < p->lovers)? p->lover[lover]: NULL;
}

int
ActualPerson_IQ(const Person* const p) {
return p->IQ;
}

Person*
ActualPerson_newLove(Person* const p, const char* const lover) {
if (NULL != lover)
if (p->lovers < LOVERS) {
strncpy(p->lover[p->lovers], lover, LENGTH);
p->lover[p->lovers][LENGTH-1] = '\0';
++(p->lovers);
}
return p;
}

int
ActualPerson_fprint(FILE* const fp, const Person* const p) {
int characters = 0;
characters += fprintf(fp, "Name: %s\n", p->name);
if (0 < p->lovers) {
characters += fprintf(fp, "lover\tname\n");
for (size_t lover = 0; lover < p->lovers; ++lover)
characters += fprintf(fp, "%3d\t%s\n",
lover, p->lover[lover]);
}
characters += fprintf(fp, "IQ: %d\n", p->IQ);
return characters;
}

void
ActualPerson_destroy(const Person* const p) {
}

const Person_virtualFunctionTable_t
Person_virtualFunctionTable = {
ActualPerson_name, ActualPerson_lover, ActualPerson_IQ,
ActualPerson_newLove, ActualPerson_fprint,
ActualPerson_destroy };

Person
Person_create(
const char* const name, const char* const lover, int IQ) {
Person P;
P.pvft = (const void*)(&Person_virtualFunctionTable);
strncpy(P.name, name, LENGTH);
P.name[LENGTH-1] = '\0';
P.lovers = 0;
ActualPerson_newLove(&P, lover);
P.IQ = IQ;
return P;
}

// virtual functions
inline static const char*
Person_name(const Person* const p) {
return ((Person_virtualFunctionTable_t*)(p->pvft))->name(p);
}

inline static const char*
Person_love(const Person* const p, size_t lover) {
return ((Person_virtualFunctionTable_t*)(p->pvft))->
love(p, lover);
}

inline static int
Person_IQ(const Person* const p) {
return ((Person_virtualFunctionTable_t*)(p->pvft))->IQ(p);
}

inline static Person*
Person_newLove(Person* const p, const char* lover) {
return ((Person_virtualFunctionTable_t*)(p->pvft))->
newLove(p, lover);
}

inline static int
Person_fprint(FILE* fp, const Person* const p) {
return ((Person_virtualFunctionTable_t*)(p->pvft))->
fprint(fp, p);
}

inline static void
Person_destroy(const Person* const p) {
((Person_virtualFunctionTable_t*)(p->pvft))->destroy(p);
}

int main(int argc, char* argv[]) {
const
Person Dan = Person_create("Dan", "Julia", 100);

Person_fprint(stdout, &Dan);
Person_destroy(&Dan);

return EXIT_SUCCESS;
}

> gcc -Wall -std=c99 -pedantic -o main main.c
> ./main

Name: Dan
lover name
0 Julia
IQ: 100

As you can plainly see,
my main program is much simpler
and works much better than yours.
The main difference between C and C++ is that
C++ does most of this stuff for you.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
trying to get an understanding of OOP in JavaScript Richard Hollenbeck Javascript 1 05-24-2009 10:43 AM
error trying to simulate NCO form quartus in matlab Juan Carlos Allica VHDL 0 07-15-2005 05:29 PM
Want to simulate logic gates usao VHDL 1 04-14-2004 07:36 AM
simulate virtual directory - I need it urgently Amir Eshterayeh ASP .Net 1 02-05-2004 01:11 PM
I cannot simulate Max VHDL 1 09-14-2003 07:57 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57