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

Help with classes

0 views
Skip to first unread message

Lorenzo Villari

unread,
Jul 19, 2002, 12:42:33 PM7/19/02
to
Hey, I know C is not C++ and this is the most debated subject in this
world, but in the end it's a C challenge...
How could one "translate" in C the code below?
I mean, not rewriting the thing C way, but creating a REAL object!

#include <iostream.h>

#define TAB '\t'

class Q {
private:
int back;
char data[10];

public:
void JoinQ(char ch);
void LeaveQ(void);
void ShowQ(void);
Q(void);
};

Q::Q()
{
back = 0;
}

void Q::ShowQ(void)
{
int x;

if (back == 0)
{
cout << "Q is empty" << endl << endl;
}
else
{
for (x = 1; x <= back; x++)
{
cout << data[x] << TAB;
}
cout << endl << endl;
}
}

void Q::JoinQ(char ch)
{
if (back < 9)
{
back++;
data[back] = ch;
}
else
cout << "Q is full" << endl;
}

void Q::LeaveQ(void)
{
int index;

for (index = 1; index < back; index++)
{
data[index] = data[index + 1];
}
back--;
}

main()
{
Q One;
One.ShowQ();
One.JoinQ('Z');
One.ShowQ();
One.JoinQ('A');
One.ShowQ();
One.JoinQ('K');
One.ShowQ();
One.LeaveQ();
One.ShowQ();
One.LeaveQ();
One.ShowQ();
One.LeaveQ();
One.ShowQ();

return(0);
}

My version compiles and links, but crashes at runtime, why?

#include <iostream.h>

#define TAB '\t'

typedef struct tagQ
{
int back;
char *data[10];

void (*JoinQ)(char *ch);
void (*LeaveQ)(void);
void (*ShowQ)(void);

struct tagQ (*Q)(void);

}Q;

Q *Q2;

Q Q()
{

Q2->back = 0;

return Q();
}

Q ShowQ(void)
{
int x;

if (Q2->back == 0)
{
printf("Q is empty\n\n");
}
else
{
for (x = 1; x <= Q2->bac

k; x++)
{


printf(Q2->data[x],TAB);
}
printf("\n\n");
}

return Q();
}

Q JoinQ(char *ch)
{
if (Q2->back < 9)
{
Q2->back++;
Q2->data[Q2->back] = ch;
}
else
printf("Q is full\n");

return Q();
}

Q LeaveQ(void)
{
int index;

for (index = 1; index < Q2->back; index++)
{
Q2->data[index] = Q2->data[index + 1];
}
Q2->back--;

return Q();
}

int main()
{

Q One;

One.ShowQ();
One.JoinQ("Z\t");
One.ShowQ();
One.JoinQ("A\t");
One.ShowQ();
One.JoinQ("K\t");
One.ShowQ();
One.LeaveQ();
One.ShowQ();
One.LeaveQ();
One.ShowQ();
One.LeaveQ();
One.ShowQ();

return(0);
}

My idea was to mimick the exact C++ syntax( :: and stuff).

I'm very interested in the macro Jacob showed in a precedent e-mail...

#define define_constructor(TYPE, defaultfn) \
TYPE *new_##TYPE(void) { TYPE *result = malloc(sizeof(TYPE)); \
memset(result,0,sizeof(TYPE)); \
result->defaultfn = defaultfn; \
return result; \
}

Jacob could you please tell me EXACTLY what it does?
I understand only part of it...

If a class is a user defined type and (I guess) the :: operator,
is an overloaded * operator, the static keyword is a kind of
"private", and all is a kind of struct allocated in memory,
how could be that I've never heard of someone who has "translated"
in C (except for ObjectiveC, but with other syntax) all the
damn thing? From what I've understood digging in gcc's sources,
classes are linked lists(or binary trees) pointing to hash tables!
The problem is I don't know what I'm talking about...

I like lost causes.
This one and trying to understand gcc's code are two of them!

Mike Caetano

unread,
Jul 19, 2002, 1:57:12 PM7/19/02
to
"Lorenzo Villari" <vll...@tiscalinet.it> wrote in message
news:ah9f8u$8c5$1...@lacerta.tiscalinet.it...

> How could one "translate" in C the code below?
> I mean, not rewriting the thing C way, but creating a REAL object!

Do you mean a real as opposed to an imaginary one? :-)

> My version compiles and links, but crashes at runtime, why?

That could be for several reasons. At a glance, it looks like no memory has
been allocated for the object, function pointers haven't been pointed to
functions and the constructor returns a call to itself resulting in an
infinite recursion.

> #include <iostream.h>
> #define TAB '\t'
> typedef struct tagQ
> {
> int back;
> char *data[10];

> void (*JoinQ)(char *ch); // these function pointers have to be
assigned a function


> void (*LeaveQ)(void);
> void (*ShowQ)(void);
> struct tagQ (*Q)(void);
> }Q;
>
> Q *Q2;
>
> Q Q()
> {
> Q2->back = 0;

> return Q(); // infinite recurse
> }

It's probably easier to start simple and work up from there.

> My idea was to mimick the exact C++ syntax( :: and stuff).

C++ hides stuff. In particular the "this" pointer.

> I'm very interested in the macro Jacob showed in a precedent e-mail...
>
> #define define_constructor(TYPE, defaultfn) \
> TYPE *new_##TYPE(void) { TYPE *result = malloc(sizeof(TYPE)); \
> memset(result,0,sizeof(TYPE)); \
> result->defaultfn = defaultfn; \
> return result; \
> }
>
> Jacob could you please tell me EXACTLY what it does?
> I understand only part of it...

No doubt Jacob can explain this better than I can, but here's my take. That
is a preprocessor macro. To make sense of it, replace TYPE with some TYPE
and defaultfn with the name of some function.

For example, let TYPE be a structure with a member pointer to function

typedef struct tagMyStruct
{
void (*foo)(void);
}
MYSTRUCT;

and let defaultfn be a function having the same signature as the member
pointer to function from MYSTRUCT

void foo(void)
{
// do stuff
}

define_constructor(MYSTRUCT, foo).

The preprocessor will perform the substitution and produce the following
code

MYSTRUCT *new_MYSTRUCT(void)
{
MYSTRUCT *result = malloc(sizeof(MYSTRUCT));
memset(result,0,sizeof(MYSTRUCT));
result-> foo = foo;
return result;
}

Analyzing this constructor function:

MYSTRUCT *new_MYSTRUCT(void)
{
MYSTRUCT *result = malloc(sizeof(MYSTRUCT)); // declare a pointer to
user defined structure and allocate memory for it
memset(result,0,sizeof(MYSTRUCT)); // set that memory to a known value,
in this case 0
result-> foo = foo; // assign address of function foo to the function
pointer member foo of the user defined structure
return result; // return the pointer
}


> If a class is a user defined type and (I guess) the :: operator,
> is an overloaded * operator, the static keyword is a kind of
> "private", and all is a kind of struct allocated in memory,
> how could be that I've never heard of someone who has "translated"
> in C (except for ObjectiveC, but with other syntax) all the
> damn thing? From what I've understood digging in gcc's sources,
> classes are linked lists(or binary trees) pointing to hash tables!
> The problem is I don't know what I'm talking about...

Before there were C++ compilers, C++ was translated into C and then
compiled. This happens much less frequently now that there are many C++
compilers available. It's not impossible.

> I like lost causes. This one and trying to understand gcc's code are two
of them!

You'll need a solid grasp of memory, pointers and in particular function
pointers, an understanding of the similarities and differences between C and
C++ and an understanding of object oriented programming. It also helps to
know what the preprocessor does. How much do you want to know? For a list of
links take a look here:
http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&th=f5260105a99f2
5ed&rnum=1

Mike


Serge Paccalin

unread,
Jul 19, 2002, 2:05:31 PM7/19/02
to
Le vendredi 19 juillet 2002 18:42:33,
"Lorenzo Villari" <vll...@tiscalinet.it> a écrit
dans comp.compilers.lcc :

Isn't this a recursive call?
Where do you allocate Q2? You need something like:

Q2 = malloc(sizeof Q);

You also have a problem with your global variable. How do you handle
two Q objects at the same time?

Moreover, where do you associate methods and actual functions?
Q2->JoinQ = JoinQ;
Q2->LeaveQ = LeaveQ;
..

>}
>
> Q ShowQ(void)
> {
> int x;
>
> if (Q2->back == 0)
> {
> printf("Q is empty\n\n");
> }
> else
> {
> for (x = 1; x <= Q2->bac
>
> k; x++)
> {
>
>
> printf(Q2->data[x],TAB);

printf("%c%c",Q2->data[x],TAB);

> }
> printf("\n\n");
> }
>
> return Q();
>}
>
> Q JoinQ(char *ch)
> {
> if (Q2->back < 9)
> {
> Q2->back++;
> Q2->data[Q2->back] = ch;
> }
> else
> printf("Q is full\n");
>
> return Q();
>}
>
> Q LeaveQ(void)
> {
> int index;
>
> for (index = 1; index < Q2->back; index++)
> {
> Q2->data[index] = Q2->data[index + 1];
> }
> Q2->back--;
>
> return Q();
>}
>
> int main()
> {
>
> Q One;

You have to call your "constructor" explicitely somewhere.
Maybe:

Q One = *Q();

> One.ShowQ();
> One.JoinQ("Z\t");
> One.ShowQ();
> One.JoinQ("A\t");
> One.ShowQ();
> One.JoinQ("K\t");
> One.ShowQ();
> One.LeaveQ();
> One.ShowQ();
> One.LeaveQ();
> One.ShowQ();
> One.LeaveQ();
> One.ShowQ();
>
> return(0);
>}

Here's my take:

<q.c> -------------------------------------------

#include <stdio.h>

#include "q.h"

#define TAB '\t'

typedef struct tagQ
{
int back;

char data[10];
};

void Q_init(Q *q)
{
q->back = 0;
}

Q *new_Q(void)
{
Q *q = malloc(sizeof Q);
Q_init(q);

return q;
}

void Q_ShowQ(Q *q)
{
int x;

if (q->back == 0)
{
printf("%s","Q is empty\n\n");
}
else
{
for (x = 1; x <= q->back; x++)
{
if (1 < x)
{
printf("%c",TAB);
}

printf("%c",q->data[x]);
}

printf("%s","\n\n");
}
}

void Q_JoinQ(Q *q,char ch)
{
if (q->back < 9)
{
q->back++;
q->data[q->back] = ch;
}
else
{
printf("%s","Q is full\n");
}
}

void Q_LeaveQ(Q *q)
{
int index;

// Shouldn't we test q->back > 1?

for (index = 1; index < q->back; index++)
{
q->data[index] = q->data[index + 1];
}
q->back--;
}

<q.h> -------------------------------------------

typedef struct tagQ Q; // you don't need more

void Q_init(Q *q);
Q *new_Q(void);
void delete_Q(Q *q);

void Q_JoinQ(Q *q,char ch);
void Q_LeaveQ(Q *q);
void Q_ShowQ(Q *q);

#define Q_(obj) Q obj; Q_init(&obj)

<main.c> ----------------------------------------

#include "q.h"

int main()
{
Q_(One); // auto

Q *pTwo = new_Q(); // heap
delete_Q(pTwo);

Q_ShowQ(&One);
Q_JoinQ(&One,'Z');
Q_ShowQ(&One);
Q_JoinQ(&One,'A');
Q_ShowQ(&One);
Q_JoinQ(&One,'K');
Q_ShowQ(&One);
Q_LeaveQ(&One);
Q_ShowQ(&One);
Q_LeaveQ(&One);
Q_ShowQ(&One);
Q_LeaveQ(&One);
Q_ShowQ(&One);

return 0;
}

-------------------------------------------------

Variables arg macros might help for the method calls:

#define Q_do(obj,meth,...) Q_##meth(&obj,__VAR_ARGS)

Q_do(One,ShowQ);
Q_do(One,JoinQ,'Z');

But I'm not sure on that one.

--
___________
_/ _ \_`_`_`_) Serge PACCALIN -- sp ad mailclub.net
\ \_L_) Il faut donc que les hommes commencent
-'(__) par n'être pas fanatiques pour mériter
_/___(_) la tolérance. -- Voltaire, 1763

Lorenzo Villari

unread,
Jul 19, 2002, 5:11:30 PM7/19/02
to
Thank you Mike, VERY much!!!
I told you I didn't know what I was talking about!!!
How much do I want to know? I want to know ANYTHING about it!!!
With all the infos I've collected by your links, I think I will study for
years!!!
But I like C, so that's ok.

Anyway... thank you all of the newsgroup, you're allways kind and
professional!!


Mike Caetano

unread,
Jul 20, 2002, 12:47:40 AM7/20/02
to
"Lorenzo Villari" <vll...@tiscalinet.it> wrote in message
news:ah9v15$gkd$1...@lacerta.tiscalinet.it...

> Thank you Mike, VERY much!!!

No problem. Don't forget to thank Serge too, he did the harder work.

> How much do I want to know? I want to know ANYTHING about it!!!

Check out the code below. You'll find similiar code among those links,
however it will most likely be obscured by macros and such. On that note,
you might find lcc's -E switches helpful when making sense of macros.

> With all the infos I've collected by your links, I think I will study for
> years!!! But I like C, so that's ok.

Lol. No doubt there are years worth of study available from the language. I
like C too.

Mike

-------------------------------------------------------------------------

/* virtfunc.c

"C++ Pointers and Dynamic Memory Management"
by Michael Daconta, Wiley & Sons 1995

*/
#include <stdio.h>
#include <stdlib.h>

void stdError(char *str, short fatal)
{
printf("%s",str);
if (fatal)
exit(1);
}

// 0. forward declare the Base "class" typedef
typedef struct Base Base;
typedef Base *Basep;

/* v Table */
typedef struct vTbl vTbl;
typedef vTbl *vTblp;
struct vTbl {
void (*print)(Basep this);
void (*set)(Basep this);
};

// 1. declare the object
/* Simple Base Class */
struct Base {
int A;
void (*construct)(Basep this);
void (*destruct)(Basep this);
vTblp vptr;
};

void construct_Base(Basep this)
{
printf("Calling Base Constructor.\n");
this->A = 0;
this->vptr = (vTblp) malloc(sizeof(vTbl));
if (!this->vptr)
stdError("Allocation Error\n",1);
}

void destruct_Base(Basep this)
{
printf("Calling Base Destructor.\n");
this->A = 0;
free(this->vptr);
}

// 2. initialize the constructor and destructor
// function pointers to the proper functions
Base INITBase = {
0, construct_Base, destruct_Base, 0 };

/* Simple Deriv1 Class */
typedef struct Deriv1 Deriv1;
typedef Deriv1 *Deriv1p;
struct Deriv1 {
Base base;
int B;
void (*construct)(Deriv1p this);
void (*destruct)(Deriv1p this);
void (*print)(Basep this);
void (*set)(Basep this);
};

void print_Deriv1(Basep this)
{
printf("A : %d.\n",this->A);
printf("B : %d.\n",((Deriv1p)this)->B);
}

void set_Deriv1(Basep this)
{
printf("A : ");
scanf("%d",&(this->A));
printf("B : ");
scanf("%d",&(((Deriv1p) this)->B));
}

void construct_Deriv1(Deriv1p this)
{
construct_Base((Basep)this);
this->base.vptr->print = print_Deriv1;
this->base.vptr->set = set_Deriv1;
printf("Calling Deriv1 Constructor.\n");
this->B = 0;
}

void destruct_Deriv1(Deriv1p this)
{
printf("Calling Deriv1 Destructor.\n");
this->B = 0;
destruct_Base((Basep)this);
}

Deriv1 INITDeriv1 = {
{
0,0 }
, 0,construct_Deriv1,destruct_Deriv1,
print_Deriv1, set_Deriv1 };

/* Simple Deriv2 Class */
typedef struct Deriv2 Deriv2;
typedef Deriv2 *Deriv2p;
struct Deriv2 {
Base base;
int C;
void (*construct)(Deriv2p this);
void (*destruct)(Deriv2p this);
void (*print)(Basep this);
void (*set)(Basep this);
};

void print_Deriv2(Basep this)
{
printf("A : %d.\n",this->A);
printf("C : %d.\n",((Deriv2p) this)->C);
}

void set_Deriv2(Basep this)
{
printf("A : ");
scanf("%d",&(this->A));
printf("C : ");
scanf("%d",&(((Deriv2p) this)->C));
}

void construct_Deriv2(Deriv2p this)
{
construct_Base((Basep)this);
this->base.vptr->print = print_Deriv2;
this->base.vptr->set = set_Deriv2;
printf("Calling Deriv2 Constructor.\n");
this->C = 0;
}

void destruct_Deriv2(Deriv2p this)
{
printf("Calling Deriv2 Destructor.\n");
this->C = 0;
destruct_Base((Basep)this);
}

Deriv2 INITDeriv2 = {
{
0,0 }
, 0,construct_Deriv2,destruct_Deriv2,
print_Deriv2, set_Deriv2 };

int main()
{
Deriv1 ob1;
Deriv2 ob2;
Basep bp1, bp2;
ob1 = INITDeriv1;
ob2 = INITDeriv2;
ob1.construct(&ob1); // 3. call constructor
ob2.construct(&ob2);

bp1 = (Basep) &ob1;
bp2 = (Basep) &ob2;

printf("Base Pointer->Deriv1 Object.\n");
bp1->vptr->set(bp1);
bp1->vptr->print(bp1);
printf("\n");

printf("Base Pointer->Deriv2 Object.\n");
bp2->vptr->set(bp2);
bp2->vptr->print(bp2);

ob1.destruct(&ob1);
ob2.destruct(&ob2);

return 0;
}

Lorenzo Villari

unread,
Jul 20, 2002, 5:41:21 PM7/20/02
to
Premised I thank you anyway even if your code doesn't work (because I get
"undefined size for.." and "Illegal use of type name Q" errors), I've
modified my thing
so now it doesn't crash, but instead of showing

Q is empty

Z

Z A

Z A K

A K

K

instead all you get is

Q is empty

Q is empty

Q is empty

Q is empty

Q is empty

Q is empty

Q is empty


Can please someone tell me why?


#include <stdio.h>

#define TAB '\t'

typedef struct tagQ
{

int back;
char *data[10];

void (*JoinQ)(char *ch);
void (*LeaveQ)(void);
void (*ShowQ)(void);

void (*_Q)(void);

}Q;

Q *new__Q(void);

void _Q(void)
{
Q *a = new__Q();
a->back = 0;
}

void ShowQ(void)
{
int x;
Q *b = new__Q();

if (b->back == 0)


{
printf("Q is empty\n\n");
}
else
{

for (x = 1; x <= b->back; x++)
{
printf(b->data[x],TAB);
}
printf("\n\n");
}
}

void JoinQ(char *ch)
{

Q *c = new__Q();

if (c->back < 9)
{
c->back++;
c->data[c->back] = ch;


}
else
printf("Q is full\n");
}

void LeaveQ(void)
{
int index;
Q *d = new__Q();

for (index = 1; index < d->back; index++)
{
d->data[index] = d->data[index + 1];
}
d->back--;
}

Q *new__Q(void)
{
Q *result = malloc(sizeof(Q));
memset(result,0,sizeof(Q));
result->_Q = _Q;
result->ShowQ = ShowQ;
result->JoinQ = JoinQ;
result->LeaveQ = LeaveQ;

return result;
}

int main()
{

Q *One = new__Q();

One->ShowQ();
One->JoinQ("Z\t");
One->ShowQ();
One->JoinQ("A\t");
One->ShowQ();
One->JoinQ("K\t");
One->ShowQ();
One->LeaveQ();
One->ShowQ();
One->LeaveQ();
One->ShowQ();
One->LeaveQ();
One->ShowQ();

return(0);
}

Mike Caetano

unread,
Jul 21, 2002, 10:51:24 AM7/21/02
to
"Lorenzo Villari" <vll...@tiscalinet.it> wrote in message
news:ahcl52$d1k$1...@lacerta.tiscalinet.it...

> Can please someone tell me why?

I saw that you asked this question at comp.lang.c too.

(http://groups.google.com/groups
?dq=&hl=en&lr=&ie=UTF-8&oe=UTF-8&th=51a24a397bc93297)

Asking a "why" question on comp.lang.c is a dangerous proposition! :-)

I think the first two responses to your question were good, but I think a
little extra comment might help you make sense of them. Ben Pfaff asked
about the use of virtual function table without corresponding members in the
"class" structure. You can examine the code from my last post for an example
of how to implement a virtual function table admist an inheritance scheme. A
virtual funtion table would allow for making calls like this,

One->ShowQ();

albeit with a few modifications to the syntax. That is, an interceding
pointer to the table and passing the instanced "object" as the first
parameter are required. (As an aside, this is the approach taken when using
COM objects in C. For a simple example take a look at IUnknown in
unknown.h.)

One->lpVtbl->ShowQ(One);

From the code of my last post, you can also see that setting up a virtual
function table involves a lot of overhead and doesn't provide much more
functionality than calling a function and passing a pointer to a structure
would. So a more typical approach to the problem would be similar to the
code that Emmanuel Delahaye presented, where each function takes a "this"
pointer to the "class" structure. One modification to Delehaye's code that I
would make is to call free from inside the destructor:

void DestroyQ (Q * this)
{
this->back = 0;
free(this);
}

If you really want to implement a virtual function table with the "Q"
example, I think Delehaye's code would be the place to start from. To do so,
add function pointer members with the appropriate signatures to the vtable
structure and inside the constructor after allocating memory for the vtable
assign the appropriate functions to those pointers.

As I said earlier, there isn't much to gain from doing this, at least not
within the same translation unit (ie. a single source file). However, this
approach can afford some encapsulation when used across multiple files in a
more complex program. I've pasted an implementation below that "hides" the
various Q functions from the main program, but I didn't go so far as to make
the implementation inheritable in the style of virtfunc.c.

Mike


-----------------------------
/*
Q.h
*/
#ifndef Q_H_
#define Q_H_

// v Table - forward declared


typedef struct vTbl vTbl;
typedef vTbl *vTblp;

// class
typedef struct tagQ Q;


struct tagQ
{
int back;
char *data[10];

vTblp vptr;
};

// v Table defined
struct vTbl {
void (*show)(Q * this);
void (*join)(Q * this, char *ch);
void (*leave)(Q * this);
};

// constructor
Q *CreateQ (void);

// destructor
void DestroyQ (Q * this);

#endif /* Q_H_ */
-----------------------------
/*
Q.c


*/
#include <stdio.h>
#include <stdlib.h>

#include <string.h>
#include "Q.h"

// any global variables in this file declared "static"
// can only be accessed by the functions in this file
static char greeting[] = "Hello World!";

static void ShowQ (Q * this)
{
int x;

if (this->back == 0)
{
printf ("%s\n", greeting);
printf ("Q is empty\n\n");
}
else
{
for (x = 1; x <= this->back; x++)
{
printf (this->data[x], '\t');
}
printf ("\n\n");
}
}

static void JoinQ (Q * this, char *ch)
{

if (this->back < 9)
{
this->back++;
this->data[this->back] = ch;
}
else
{
printf ("Q is full\n");
}
}

static void LeaveQ (Q * this)
{
int index;

for (index = 1; index < this->back; index++)
{
this->data[index] = this->data[index + 1];
}
this->back--;
}


Q *CreateQ (void)
{
Q *this = malloc (sizeof (*this));

if (this)
{
memset (this, 0, sizeof (*this));
}

this->vptr = malloc( sizeof (*(this->vptr)) );

if ( this->vptr )
{
this->vptr->show = ShowQ;
this->vptr->join = JoinQ;
this->vptr->leave = LeaveQ;
}

return this;

}


void DestroyQ (Q * this)
{
this->back = 0;
free(this->vptr);
free(this);
}

-----------------------------
/*
Qtest.c
*/
#include "Q.h"

int main (void)
{

Q *One = CreateQ ();

if (One)
{
One->vptr->show(One);
One->vptr->join(One, "Z\t");
One->vptr->show(One);
One->vptr->join(One, "A\t");
One->vptr->show(One);
One->vptr->join(One, "K\t");
One->vptr->show(One);
One->vptr->leave(One);
One->vptr->show(One);
One->vptr->leave(One);
One->vptr->show(One);
One->vptr->leave(One);
One->vptr->show(One);

DestroyQ (One);

}
return 0;
}

Mike Caetano

unread,
Jul 21, 2002, 11:18:40 AM7/21/02
to
"Serge Paccalin" <s...@mailclub.no.spam.net> wrote in message
news:Xns9250C75409D...@127.0.0.1...

> Here's my take:
> <q.c> -------------------------------------------

Oops, I should have taken a closer look at your code before adapting
Delahaye's.

> -------------------------------------------------
> Variables arg macros might help for the method calls:
> #define Q_do(obj,meth,...) Q_##meth(&obj,__VAR_ARGS)
> Q_do(One,ShowQ);
> Q_do(One,JoinQ,'Z');
> But I'm not sure on that one.

I agree, however, afaik lccwin32 does not yet implement variable argument
macros (ie __VAR_ARGS ). Jacob commented on this a week ago or thereabout.

Mike


Doyle Whisenant

unread,
Jul 21, 2002, 2:46:04 PM7/21/02
to

Is is possible to capture the errors output from lrc when compiling a
*.rc file from an editor. If so, how? I'm writing an front end (editor)
for BCX and need to capture the errors from lrc. The compiler and linker
make it easy to write the errors to a file but not lrc.

Anyway of doing this using STDOUT with lrc? Anyway at all?

Thanks!

--
Doyle Whisenant
mech...@sonet.net
http://www.mechanic.0catch.com/

Lorenzo Villari

unread,
Jul 21, 2002, 2:53:51 PM7/21/02
to

> No problem. Don't forget to thank Serge too, he did the harder work.
In fact I've thanked you and then him in another e-mail...
Anyway... THANK YOU Serge!

The only reason for my crossposting to comp.lang.c has been the fact that,
for a moment I've thought the e-mail to this group had faded away in a
"black hole" (hmm... this reminds me something....).
In fact it seemed lost even the one sent to comp.lang.c, and now you inform
me that instead somebody replied me? GOOD!!! I can't wait to read 'em!
I'm gonna test all the codes, read all the emails and study: I think it's
gonna be a long long time!!! ( I'm a rocket maaan... )


Lorenzo Villari

unread,
Jul 21, 2002, 6:37:33 PM7/21/02
to
I would like to add

> however it will most likely be obscured by macros and such. On that note,
> you might find lcc's -E switches helpful when making sense of macros.

How much helpful? I've already used them and macros desappear!!!
It will be VERY useful something to see to what the preprocessor expand
those macros: this way you CAN'T do syntax errors because you always
know EXACTLY to what they are "translated"!!!

> Asking a "why" question on comp.lang.c is a dangerous proposition! :-)

Yeah I know, I don't like that attitude.

> COM objects in C. For a simple example take a look at IUnknown in
> unknown.h.)

IUnknown? unknown.h? What are you talking about?
Anyway, I'm interested in it.

> Oops, I should have taken a closer look at your code before adapting
> Delahaye's.

Why do you say so? His code (although similar to Delahaye's) doesn't work!


(because I get "undefined size for.." and "Illegal use of type name Q"
errors)

By the way your code (Delahaye's) work!


Doyle Whisenant

unread,
Jul 21, 2002, 8:23:34 PM7/21/02
to
Craig Williams wrote:
>
> Boy, are you in for it. It took me a lot of
> research and playing around to get this. Since
> you are calling the program from another, you are
> probably using CreateProcess(). If you aren't,
> switch, I guess.

Yes, I am using CreateProcess().

> CreateProcess() let's you get a
> handle to the child process' stdin, stdout,
> stderror. If you look on my website, about
> halfway down you'll see a link called Code for
> I/O Redirection.

Thanks for the links, Craig. I'm off to read up on all of this. I
appreciate it!

Serge Paccalin

unread,
Jul 22, 2002, 12:56:15 AM7/22/02
to
Le dimanche 21 juillet 2002 20:53:51,

"Lorenzo Villari" <vll...@tiscalinet.it> a écrit
dans comp.compilers.lcc :

>> No problem. Don't forget to thank Serge too, he did the harder


>> work.
> In fact I've thanked you and then him in another e-mail...
> Anyway... THANK YOU Serge!

You're welcome. But you were right, there were problems with my code:
you can't make auto objects with it, only heap objects.

Mike Caetano

unread,
Jul 22, 2002, 4:38:36 AM7/22/02
to
"Lorenzo Villari" <vll...@tiscalinet.it> wrote in message
news:ahfcqe$ffu$1...@lacerta.tiscalinet.it...

> > COM objects in C. For a simple example take a look at IUnknown in
> > unknown.h.)
> IUnknown? unknown.h? What are you talking about?
> Anyway, I'm interested in it.

Here is the IUnknown interface. All COM objects must implement this.

typedef struct IUnknown IUnknown;
typedef struct IUnknownVtbl {
HRESULT (__stdcall *QueryInterface)(IUnknown *, REFIID, void **);
ULONG (__stdcall *AddRef)(IUnknown *);
ULONG (__stdcall *Release)(IUnknown *);
} IUnknownVtbl;
struct IUnknown { struct IUnknownVtbl *lpVtbl; };

#define IUnknown_QueryInterface(This,riid,ppvObject) \
(This)->lpVtbl->QueryInterface(This,riid,ppvObject)
#define IUnknown_AddRef(This) (This)->lpVtbl->AddRef(This)
#define IUnknown_Release(This) (This)->lpVtbl->Release(This)

These macros don't have to be used, but they illustrate how the methods are
called. One thing to note regarding IUnknown and COM is that only the
interface is exposed. The data items of the "class" are hidden inside the
implementation file. Take a look at the comlib example at John's website
(http://www.john.findlay1.btinternet.co.uk/OLE/ole.htm) for details. In
contrast, a C++ class definition contains the data members, in similar
fashion to the tagQ structure definition that I wrote.

Mike


Mike Caetano

unread,
Jul 22, 2002, 4:42:19 AM7/22/02
to
"Serge Paccalin" <s...@mailclub.no.spam.net> wrote in message
news:Xns9252EABFBCE...@127.0.0.1...

> you can't make auto objects with it, only heap objects.

That's too bad. I thought that part of your code was interesting and I tried
to figure out how to incorporate a vtable that way but couldn't see how to
do it without a heap allocation.

Mike


0 new messages