473,614 Members | 2,428 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

[Slightly OT] Trying to simulate OOP with C

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(simul ated class) template:
-----------------------------------------------

struct PersonTag
{
char name[40];
char loves[20][40];
int IQ;
char *(*setname)(con st char *, struct PersonTag *);
char *(*setlover)(co nst 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(D an);

Dan.NAME("Dan") ;
Dan.LOVER("Juli a", 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("T eresa" , &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

Nov 14 '05 #1
4 2226

"Deniz Bahar" <de*********@gm ail.com> wrote in message
news:11******** **************@ f14g2000cwb.goo glegroups.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
Nov 14 '05 #2
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(Cl assName) 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(simul ated class) template:
-----------------------------------------------

struct PersonTag
{
char name[40];
char loves[20][40];
int IQ;
char *(*setname)(con st char *, struct PersonTag *);
char *(*setlover)(co nst 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(D an);

Dan.NAME("Dan") ;
Dan.LOVER("Juli a", 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("T eresa" , &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.
Nov 14 '05 #3
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.
Nov 14 '05 #4
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(simul ated class) template:
-----------------------------------------------

struct PersonTag {
char name[40];
char loves[20][40];
int IQ;
char *(*setname)(con st char *, struct PersonTag *);
char *(*setlover)(co nst 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(D an);

Dan.NAME("Dan") ;
Dan.LOVER("Juli a", 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("T eresa" , &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_virtualF unctionTable_t {
const char* (*name)(const Person*);
const char* (*love)(const Person*, size_t);
int (*IQ)(const Person*);
Person* (*newLove)(Pers on*, const char*);
int (*fprint)(FILE* , const Person*);
void (*destroy)(cons t Person*);
} Person_virtualF unctionTable_t;

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

const char*
ActualPerson_lo ver(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_ne wLove(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_fp rint(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_de stroy(const Person* const p) {
}

const Person_virtualF unctionTable_t
Person_virtualF unctionTable = {
ActualPerson_na me, ActualPerson_lo ver, ActualPerson_IQ ,
ActualPerson_ne wLove, ActualPerson_fp rint,
ActualPerson_de stroy };

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

// virtual functions
inline static const char*
Person_name(con st Person* const p) {
return ((Person_virtua lFunctionTable_ t*)(p->pvft))->name(p);
}

inline static const char*
Person_love(con st Person* const p, size_t lover) {
return ((Person_virtua lFunctionTable_ t*)(p->pvft))->
love(p, lover);
}

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

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

inline static int
Person_fprint(F ILE* fp, const Person* const p) {
return ((Person_virtua lFunctionTable_ t*)(p->pvft))->
fprint(fp, p);
}

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

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

Person_fprint(s tdout, &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.
Nov 14 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
11252
by: Christian | last post by:
Hello, As the subject says it, is there a way to simulate a special keypress in JS ? In my case, on loading an HTML page, i'd like to set the cursor at the end of the input text of an <input type=text ...> object. focus() sets the cusor at the beginning Any idea ? Christian.
10
2736
by: JustSomeGuy | last post by:
I need to log into a web page automatically. The web page has a password text field and a login button. (A form?) How do I simulate that a user logged in and entered the password and pressed the login button? TIA.
2
2677
by: dast | last post by:
I want to simulate an input and post into a web page and than download the web page that is opened after the correct input! The web page exists of an user input form with userid and password, after input the correct data and pressing the submit button another web page will be opened. I have tried to download the web page with the following code (I am using the CAmHttpSocket class at http://www.codeproject.com/internet/amhttputils.asp):
61
16228
by: /* frank */ | last post by:
I have to do a homework: make a CPU simulator using C language. I have a set of asm instructions so I have to write a program that should: - load .asm file - view .asm file - do a step by step simulation - display registers contents I tried to search con google with no success.
4
5169
by: johnny | last post by:
On a form I would like to simulate a button click when the Enter is pressed. My form is setup and it works if the delegate for the key pressed on the form calls the delegate for the button pressed. But can we simulate a button click instead? This way if later the delegate is changed for the button, we don't forget to do the changes on other events?
4
1913
by: Garry Freemyer | last post by:
I'm trying to convert this macro to a c# function but I have a big problem. It's on the LEFT side of an assignment statement and I am extremely flustered over this one because I'm a little rusty and have been struggling over this for days, not wanting to show all my ignorance in final desparate plea for help which this is ... Here is the macro ... #define X(t,b) (sp->x)
1
2210
by: diegocarpintero | last post by:
I am writing a c# class which main purpose is to simulate the dialog with a GUI-application. The idea is that this class can simulate some user actions like mouse clicks on buttons. I have found the following possibilities to simulate it: 1) Use SendInput Function (user32.dll) (unmanaged code) 2) Use System.Windows.Forms.SendKeys (managed code)
1
3036
by: =?Utf-8?B?UmljYXJkbyBRdWludGFuaWxsYQ==?= | last post by:
how to simulate a different time zone? ¿is it possible by code to simulate that i am in a different time zone just for to execute a few lines of code? in my case i am in the time zone "Santiago/Chile" which is GMT-04, but for to execute a few lines of code that demand time zone "GMT 0" i need to change or simulate de time zone "GMT 0" how can i do that?
4
2074
by: c0mm3nt | last post by:
Hi Guys. I'm writing a web crawler (web spider) that crawl all links in a website. My application is a Win32 App, written in C# with .Net framework 3.5. Now I'm using HttpWebRequest an HttpWebResponse to communicate with the web server. I also built my own Http Parser that can parse anything I want. I found all link like "href", "src", "action"... in the parse. But I can not solve one problem: Simulate Client Script in the page (like JS...
0
8179
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8124
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8621
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8427
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7050
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6087
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5538
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4119
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
1712
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.