Port code from C++ to C?

P

PengYu.UT

Hi,

I have to use some machine with only support of C. But I have some C++
programs, which use most C++ comman features. Is there any way to
convert those C++ programs to C?

Or is there any way that I can mimic C++ by C? So that even if I have
to recode, I don't have to change the C++ code structures.

Thanks!

Best wishes,
Peng
 
P

PengYu.UT

Thank you for your reply! But this thread doesn't address all I want.

Not only I want port C++ to C (not necessarily by a preprocessor), I
also want the C code human readable.

So the problem right now is that how to implement OO in C language.
I've read some old OO book which discuss this issue, because there were
no enough OO support at that time. But I forget the title of the book.

If you can give me any relevant information, it will be great.

Peng
 
W

Walter Roberson

Thank you for your reply! But this thread doesn't address all I want.
Not only I want port C++ to C (not necessarily by a preprocessor), I
also want the C code human readable.

You indicated that you wanted to mimic C++ in C. The result is
not very likely to be human readable.

So the problem right now is that how to implement OO in C language.

Don't. If you need C++ then use C++. If you don't need C++ then
write in C paradigms, not in C++ paradigms. Any attempt to write a
hybrid is likely to end up with ugly code.
 
G

gooch

Thank you for your reply! But this thread doesn't address all I want.

Not only I want port C++ to C (not necessarily by a preprocessor), I
also want the C code human readable.

So the problem right now is that how to implement OO in C language.
I've read some old OO book which discuss this issue, because there were
no enough OO support at that time. But I forget the title of the book.

If you can give me any relevant information, it will be great.

Peng

You can do everything with C that you can do with C++ but if the code
is heavily dependent on OO features of C++ it is likely to be very
difficult to read if you simply translate it as is to C. You are
probably better of reverse engineering it and developing a design from
the existing C++ code and then adjusting the design to be implemented
in C using its strengths and then re-coding it.
 
J

John Devereux

Thank you for your reply! But this thread doesn't address all I want.

Not only I want port C++ to C (not necessarily by a preprocessor), I
also want the C code human readable.

So the problem right now is that how to implement OO in C language.
I've read some old OO book which discuss this issue, because there were
no enough OO support at that time. But I forget the title of the book.

Miro Samek discussed this extensively as part of his book "Practical
Statecharts in C/C++". He called the implementation "C+". You can
download the manual and source code from his web site
<http://www.quantum-leaps.com/devzone/cookbook.htm#OOP>.
 
P

PengYu.UT

I'm sorry that I cann't download this manual. It seems the above link
is dead. If you have a copy would please email it to me as attachment.
Thanks,

Peng
 
J

Jonathan Bartlett

To do OO in C, you usually do something like this:

C++ Class
---------
class foo
{
int a;
virtual void bar() { a = 3; }
virtual void abc() { a = 4; }
};

class doo : public foo
{
int b;
void bar() { b = 5; } /* overrides the original bar */
virtual void xzy() { b = 6; }
};

The C Version:
--------------
struct foo;
struct vtable_foo
{
void (*bar)(struct foo*);
void (*abc)(struct foo*);
};
struct vtable_foo __vtable_foo;

struct foo
{
struct vtable_foo *vtbl;
int a;
};

void foo_bar(struct foo *f)
{
f->a = 3;
}

void foo_abc(struct foo *f)
{
f->a = 4;
}

/* class initializer -- must be run EXACTLY ONCE before creating any
instances of foo */
void initialize_foo_class()
{
__vtable_foo.bar = foo_bar;
__vtable_foo.abc = foo_abc;
}

/* constructor */
void foo_initialize(struct foo *f)
{
f->vtbl = &__vtable_foo;
f->a = 0;
}

struct doo;
struct vtable_doo
{
void (*bar)(struct doo*);
void (*abc)(struct doo*);
void (*xyz)(struct doo*);
};
struct vtable_doo __vtable_doo;

struct doo
{
struct vtable_doo *vtbl;
int a; /* from foo */
int b;
};

void doo_bar(struct doo *d)
{
d->b = 5;
}

void doo_xyz(struct doo *d)
{
d->b = 6;
}

void initialize_doo_class()
{
/* inherited from foo */
__vtable_doo.bar = doo_bar; /* overriden in doo */
__vtable_doo.abc = foo_abc;

/* new in doo */
__vtable_doo.xyz = doo_xyz;
}

void doo_initialize(struct doo *d)
{
d->vtbl = &__vtable_doo;
d->a = 0;
d->b = 0;
}

int main()
{
struct foo *f1;
struct foo *f2;
struct doo *d1;

initialize_foo_class();
initialize_doo_class();

d1 = malloc(sizeof(struct doo));
doo_initialize(d1);
f1 = malloc(sizeof(struct foo));
foo_initialize(f1);
f2 = d1;
(d1->vtbl->xyz)(d1); /* this sets d1->b to 6 */
printf("d1->b is %d\n", d1->b);
(f2->vtbl->bar)(f2); /* this sets d1->b to 5, because it is invoke via
vtable */
printf("d1->b is %d\n", d1->b);
(f1->vtbl->bar)(f1); /* this sets f1->a to 3 */
printf("d1->a is %d\n", f1->a);

return 0;
}

----end program----

The problem w/ this approach is (a) its messy and error prone, and (b)
it only supports direct single-line inheritance. If you want to use
multiple inheritance or even mixin classes (abstract classes like java
interfaces), it gets much trickier, and (c) you have to do a LOT of writing.

Also, while we're on the topic you might check out my article on
closures in C, which relates very closely to what we're doing here:

http://www-128.ibm.com/developerworks/linux/library/l-highfunc.html

Jon
 
C

Chris Hills

Hi,

I have to use some machine with only support of C. But I have some C++
programs, which use most C++ comman features. Is there any way to
convert those C++ programs to C?

Or is there any way that I can mimic C++ by C? So that even if I have
to recode, I don't have to change the C++ code structures.

Thanks!

Best wishes,
Peng

I Think this solves your problem: Comeau C++ compiler generates C as its
object code.

Comeau C/C++ 4.3.3: Watch for our Mac port
Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries. Have you tried it?
(e-mail address removed) http://www.comeaucomputing.com
 
J

John Devereux

I'm sorry that I cann't download this manual. It seems the above link
is dead. If you have a copy would please email it to me as attachment.

My mail to you bounced with "illegal attachment" so I guess you are
stuck! I downloaded the file myself earlier today, but now the link
seems to be broken as you say. Perhaps it will work again soon!
 
R

Roger Leigh

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Jonathan Bartlett said:
To do OO in C, you usually do something like this:

The C Version:
--------------
struct foo;
struct vtable_foo
{
void (*bar)(struct foo*);
void (*abc)(struct foo*);
};
struct vtable_foo __vtable_foo;
/* class initializer -- must be run EXACTLY ONCE before creating any
instances of foo */
void initialize_foo_class()
{
__vtable_foo.bar = foo_bar;
__vtable_foo.abc = foo_abc;
}

/* constructor */
void foo_initialize(struct foo *f)
{
f->vtbl = &__vtable_foo;
f->a = 0;
}

struct doo;
struct vtable_doo
{
void (*bar)(struct doo*);
void (*abc)(struct doo*);
void (*xyz)(struct doo*);
};
struct vtable_doo __vtable_doo;
void initialize_doo_class()
{
/* inherited from foo */
__vtable_doo.bar = doo_bar; /* overriden in doo */
__vtable_doo.abc = foo_abc;

/* new in doo */
__vtable_doo.xyz = doo_xyz;
}

void doo_initialize(struct doo *d)
{
d->vtbl = &__vtable_doo;
d->a = 0;
d->b = 0;
}

The problem with this scheme is that your initialisers don't take a
vtable as a parameter. This prevents "chaining up" in inherited
vtables. You had to duplicate vtable_foo /by hand/ in vtable_doo.
This is messy, and won't scale: if you now alter vtable_foo, your code
is broken (you can't cast between the two types). What you really
want is:

typedef struct _FooClass
{
void (*bar)(struct foo*);
void (*abc)(struct foo*);
} FooClass;

typedef struct _DooClass
{
FooClass parent;
void (*xyz)(struct doo*);
} DooClass;

You can now freely cast between them, with no worries about a changing
API.
The problem w/ this approach is (a) its messy and error prone, and (b)
it only supports direct single-line inheritance. If you want to use
multiple inheritance or even mixin classes (abstract classes like java
interfaces), it gets much trickier, and (c) you have to do a LOT of
writing.

There are good libraries to help with this, such as GObject. They
handle interfaces, though multiple inheritance is asking too much (and
is of dubious value in any case).


Regards,
Roger

- --
Roger Leigh
Printing on GNU/Linux? http://gimp-print.sourceforge.net/
Debian GNU/Linux http://www.debian.org/
GPG Public Key: 0x25BFB848. Please sign and encrypt your mail.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Processed by Mailcrypt 3.5.8 <http://mailcrypt.sourceforge.net/>

iD8DBQFClLorVcFcaSW/uEgRAolJAKDmSCdtuD9jitRBDdBPigTTC2XqBQCgvTAq
O4V8mnpDwi71CqDCaRX4FQo=
=eDbg
-----END PGP SIGNATURE-----
 
E

E. Robert Tisdale

Jonathan said:
To do OO in C, you usually do something like this:
[snip]
> cat main.c
#include <stdio.h>

typedef struct foo {
const
void* vtbl;
int a;
} foo;

typedef struct vtable_foo {
void (*bar)(foo*);
void (*abc)(foo*);
} vtable_foo;

void actual_foo_bar(foo* p) {
p->a = 3;
}

inline /* virtual */
void foo_bar(foo* p) {
((vtable_foo*)(p->vtbl))->bar(p);
}

void actual_foo_abc(foo* p) {
p->a = 4;
}

inline /* virtual */
void foo_abc(foo* p) {
((vtable_foo*)(p->vtbl))->abc(p);
}

// [Unnecessary] class initializer --
// must be run EXACTLY ONCE
// need *never* be run.
// before creating any instances of foo
//void initialize_foo_class(void) {
// __vtable_foo.bar = foo_bar;
// __vtable_foo.abc = foo_abc;
// }

const
vtable_foo __vtable_foo = {actual_foo_bar,
actual_foo_abc};

// [No. This is not a] constructor.
// This is an initializer.
inline
void foo_initialize(foo *p) {
p->vtbl = (void*)(&__vtable_foo);
p->a = 0;
}

// This is a [pseudo] constructor.
inline
foo foo_create(void) {
foo f;
foo_initialize(&f);
return f;
}

// Always define a destructor
// even if it doesn't do anything.
inline
void foo_destroy(const foo* p) { }


//typedef struct doo {
// vtable_doo* vtbl;
// int a; // from foo
// int b;
// } doo;

typedef struct doo {
foo f;
int b;
} doo;

typedef struct vtable_doo {
void (*bar)(doo*);
void (*abc)(foo*);
void (*xyz)(doo*);
} vtable_doo;

void actual_doo_bar(doo* p) {
p->b = 5;
}

inline /* virtual */
void doo_bar(doo* p) {
((vtable_doo*)(p->f.vtbl))->bar(p);
}

inline /* virtual */
void doo_abc(doo* p) {
((vtable_doo*)(p->f.vtbl))->abc((foo*)p);
}

void actual_doo_xyz(doo* p) {
p->b = 6;
}

inline /* virtual */
void doo_xyz(doo* p) {
((vtable_doo*)(p->f.vtbl))->xyz(p);
}

// Unnecessary "class" initializer.
//void initialize_doo_class(void) {
// // inherited from foo
// __vtable_doo.bar = doo_bar; /* overriden in doo */
// __vtable_doo.abc = foo_abc;
//
// // new in doo
// __vtable_doo.xyz = doo_xyz;
// }

const
vtable_doo __vtable_doo = {actual_doo_bar,
actual_foo_abc,
actual_doo_xyz};

// This is an initializer.
inline
void doo_initialize(doo* p) {
p->f.vtbl = (void*)(&__vtable_doo);
p->f.a = 0;
p->b = 0;
}

// This is a [pseudo] constructor.
inline
doo doo_create(void) {
doo d;
doo_initialize(&d);
return d;
}

// Always define a destructor
// even if it doesn't do anything.
inline
void doo_destroy(const doo* p) { }

int main(int argc, char* argv[]) {
doo d1 = doo_create();
foo f1 = foo_create();
foo* p = &(d1.f);

doo_xyz(&d1); // This sets d1.b to 6.
printf("d1.b is %d\n", d1.b);

foo_bar(p); // This sets d1.b to 5
// because it is invoked via vtable.
printf("d1.b is %d\n", d1.b);

foo_bar(&f1); // This sets f1.a to 3.
printf("f1.a is %d\n", f1.a);

foo_destroy(&f1); // Always call the destructors
doo_destroy(&d1); // even if they don't do anything.

return 0;
}
> gcc -Wall -std=c99 -pedantic -o main main.c
> ./main
d1.b is 6
d1.b is 5
f1.a is 3
 
C

CBFalconer

I'm sorry that I cann't download this manual. It seems the above
link is dead. If you have a copy would please email it to me as
attachment. Thanks,

What manual? There is no link above, because you failed to quote
adequately. Who is 'you'? See my sig, below.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,044
Latest member
RonaldNen

Latest Threads

Top