linux-c-programming.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* mixing C/C++
@ 2003-11-08  9:30 Elias Athanasopoulos
  2003-11-08 13:36 ` James Stevenson
  2003-11-10 15:00 ` Matthew Studley
  0 siblings, 2 replies; 19+ messages in thread
From: Elias Athanasopoulos @ 2003-11-08  9:30 UTC (permalink / raw)
  To: linux-c-programming

Hello!

I want to create Ruby bindings for a C++ project, so my first
step is to call C++ code from C, since Ruby has a plain C API.

Consider I have a Foo class which its implementation is compiled
in a shared lib (libtest.so). I have a second wrapper lib:

#include "libtest.h"

extern "C" class Foo *  wrap_foo_ctor() { return new Foo(); }
extern "C" void wrap_foo_set_food(Foo *f, int i) { f->set_food(i); }
extern "C" int  wrap_foo_hello(Foo *f) { return f->hello();  }

Using the above my C program is:

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

int main(void)
{
  struct Foo *m = (struct Foo*) wrap_foo_ctor();

  wrap_foo_set_food(m, 10);
  wrap_foo_hello(m);

  free(m);

  return 1;
}

And:

elathan@velka:~/src/bindings> gcc foo.c -Wall  -ltest -lwrap -o foo -L/home/elathan/src/bindings
foo.c: In function `main':
foo.c:6: warning: implicit declaration of function `wrap_foo_ctor'
foo.c:8: warning: implicit declaration of function `wrap_foo_set_food'
foo.c:9: warning: implicit declaration of function `wrap_foo_hello'
elathan@velka:~/src/bindings> ./foo
10


My main question is how to silent the implicit declaration warning in
gcc, which is, of course, correct. I want everything to compile with -Wall. 
Is there a warkaround? 

I tried to create a C header file, but I don't know how to make a C prototype
of:

 class Foo *  wrap_foo_ctor() { return new Foo(); }

Or silent the 'icompatible pointer type' warning in declarations, such as:

 int  wrap_foo_hello(Foo *f) { return f->hello();  }

TIA,
-- 
University of Athens			I bet the human brain 
Physics Department				is a kludge --Marvin Minsky 

	

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: mixing C/C++
  2003-11-08  9:30 mixing C/C++ Elias Athanasopoulos
@ 2003-11-08 13:36 ` James Stevenson
  2003-11-10 15:00 ` Matthew Studley
  1 sibling, 0 replies; 19+ messages in thread
From: James Stevenson @ 2003-11-08 13:36 UTC (permalink / raw)
  To: Elias Athanasopoulos; +Cc: linux-c-programming


Hi

this is because you program doesnt know what the functions
are called so you need to add protypes.

Either create a  header and put a prototype of the
function name in there and include the header file

or

add the prototypes to the top of the C file.

	James

On Sat, 8 Nov 2003, Elias Athanasopoulos wrote:

> Hello!
> 
> I want to create Ruby bindings for a C++ project, so my first
> step is to call C++ code from C, since Ruby has a plain C API.
> 
> Consider I have a Foo class which its implementation is compiled
> in a shared lib (libtest.so). I have a second wrapper lib:
> 
> #include "libtest.h"
> 
> extern "C" class Foo *  wrap_foo_ctor() { return new Foo(); }
> extern "C" void wrap_foo_set_food(Foo *f, int i) { f->set_food(i); }
> extern "C" int  wrap_foo_hello(Foo *f) { return f->hello();  }
> 
> Using the above my C program is:
> 
> #include <stdio.h>
> #include <stdlib.h>
> 
> int main(void)
> {
>   struct Foo *m = (struct Foo*) wrap_foo_ctor();
> 
>   wrap_foo_set_food(m, 10);
>   wrap_foo_hello(m);
> 
>   free(m);
> 
>   return 1;
> }
> 
> And:
> 
> elathan@velka:~/src/bindings> gcc foo.c -Wall  -ltest -lwrap -o foo -L/home/elathan/src/bindings
> foo.c: In function `main':
> foo.c:6: warning: implicit declaration of function `wrap_foo_ctor'
> foo.c:8: warning: implicit declaration of function `wrap_foo_set_food'
> foo.c:9: warning: implicit declaration of function `wrap_foo_hello'
> elathan@velka:~/src/bindings> ./foo
> 10
> 
> 
> My main question is how to silent the implicit declaration warning in
> gcc, which is, of course, correct. I want everything to compile with -Wall. 
> Is there a warkaround? 
> 
> I tried to create a C header file, but I don't know how to make a C prototype
> of:
> 
>  class Foo *  wrap_foo_ctor() { return new Foo(); }
> 
> Or silent the 'icompatible pointer type' warning in declarations, such as:
> 
>  int  wrap_foo_hello(Foo *f) { return f->hello();  }
> 
> TIA,
> 


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: mixing C/C++
  2003-11-08  9:30 mixing C/C++ Elias Athanasopoulos
  2003-11-08 13:36 ` James Stevenson
@ 2003-11-10 15:00 ` Matthew Studley
  2003-11-10 17:37   ` Elias Athanasopoulos
  1 sibling, 1 reply; 19+ messages in thread
From: Matthew Studley @ 2003-11-10 15:00 UTC (permalink / raw)
  To: Elias Athanasopoulos, linux-c-programming

Have you considered using SWIG to automatically generate your wrappers?

... SWIG is a software development tool that connects programs written in C
and C++ with a variety of high-level programming languages. SWIG is
primarily used with common scripting languages such as Perl, Python, Tcl/Tk,
and Ruby...

http://www.swig.org/

May be a useful resource.  I've used it with C and Python.

regards

Matt

----- Original Message -----
From: Elias Athanasopoulos <elathan@phys.uoa.gr>
To: <linux-c-programming@vger.kernel.org>
Sent: Saturday, November 08, 2003 9:30 AM
Subject: mixing C/C++


> Hello!
>
> I want to create Ruby bindings for a C++ project, so my first
> step is to call C++ code from C, since Ruby has a plain C API.
>
> Consider I have a Foo class which its implementation is compiled
> in a shared lib (libtest.so). I have a second wrapper lib:
>
> #include "libtest.h"
>
> extern "C" class Foo *  wrap_foo_ctor() { return new Foo(); }
> extern "C" void wrap_foo_set_food(Foo *f, int i) { f->set_food(i); }
> extern "C" int  wrap_foo_hello(Foo *f) { return f->hello();  }
>
> Using the above my C program is:
>
> #include <stdio.h>
> #include <stdlib.h>
>
> int main(void)
> {
>   struct Foo *m = (struct Foo*) wrap_foo_ctor();
>
>   wrap_foo_set_food(m, 10);
>   wrap_foo_hello(m);
>
>   free(m);
>
>   return 1;
> }
>
> And:
>
> elathan@velka:~/src/bindings> gcc foo.c -Wall  -ltest -lwrap -o
foo -L/home/elathan/src/bindings
> foo.c: In function `main':
> foo.c:6: warning: implicit declaration of function `wrap_foo_ctor'
> foo.c:8: warning: implicit declaration of function `wrap_foo_set_food'
> foo.c:9: warning: implicit declaration of function `wrap_foo_hello'
> elathan@velka:~/src/bindings> ./foo
> 10
>
>
> My main question is how to silent the implicit declaration warning in
> gcc, which is, of course, correct. I want everything to compile
with -Wall.
> Is there a warkaround?
>
> I tried to create a C header file, but I don't know how to make a C
prototype
> of:
>
>  class Foo *  wrap_foo_ctor() { return new Foo(); }
>
> Or silent the 'icompatible pointer type' warning in declarations, such as:
>
>  int  wrap_foo_hello(Foo *f) { return f->hello();  }
>
> TIA,
> --
> University of Athens I bet the human brain
> Physics Department is a kludge --Marvin Minsky
>
>
> -
> To unsubscribe from this list: send the line "unsubscribe
linux-c-programming" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>
> This incoming email to UWE has been independently scanned for viruses and
any virus detected has been removed using McAfee anti-virus software
>
>
>


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: mixing C/C++
  2003-11-10 15:00 ` Matthew Studley
@ 2003-11-10 17:37   ` Elias Athanasopoulos
  2003-11-12  4:35     ` convert INT to CHAR but print's BEEP J.
  0 siblings, 1 reply; 19+ messages in thread
From: Elias Athanasopoulos @ 2003-11-10 17:37 UTC (permalink / raw)
  To: Matthew Studley; +Cc: linux-c-programming

On Mon, Nov 10, 2003 at 03:00:31PM -0000, Matthew Studley wrote:
> Have you considered using SWIG to automatically generate your wrappers?
> 
> ... SWIG is a software development tool that connects programs written in C
> and C++ with a variety of high-level programming languages. SWIG is
> primarily used with common scripting languages such as Perl, Python, Tcl/Tk,
> and Ruby...

Yes, I have tried it. I found it quite complicated in the sense 
that I can't control stuff; it's difficult to hack the auto-generated
swig files. Also, it lacks compatibility with Ruby 1.8.

Thanks for your reply.

Regards,
-- 
University of Athens			I bet the human brain 
Physics Department				is a kludge --Marvin Minsky 

	

^ permalink raw reply	[flat|nested] 19+ messages in thread

* convert INT to CHAR but print's BEEP...
  2003-11-10 17:37   ` Elias Athanasopoulos
@ 2003-11-12  4:35     ` J.
  2003-11-12  7:11       ` Mikael Aronsson
  2003-11-13  6:36       ` convert INT to CHAR but print's BEEP Jeff Woods
  0 siblings, 2 replies; 19+ messages in thread
From: J. @ 2003-11-12  4:35 UTC (permalink / raw)
  To: linux-c-programming

Wednesday, November 12 05:19:21

Hello, I have kind of a problem with converting an int to a char.
The get_rand_str() function returns an string build of random 
charaters with a max length of int `MAX'.

This seems to work at first glance: 
~: ./program 
qqxfrd

However if I examen the output closer:
~: ./program | od -a
0000000   q   q soh   x stx   f etx   r eot   d enq  nl
0000014

Now I know why my computer keeps beeping everytime it
outputs a string :-)

What is the correct way of changing the int value to a
char value so that I can append it to the return string ?

char *get_rand_str(int max) {
 int i = 0;
 char value;
 char *retval = NULL;

 for(; i < max; i++) {
  value = get_ascii_code(97, 122);
  retval = (char *)realloc(retval, sizeof(char));
  strcat(retval, &value);
 }

 return retval;
 free(retval);
}

int get_ascii_code(int low, int high) {
 int k = 0;
 double d = 0;

 d = (double)rand() / ((double)RAND_MAX + 1);
 k = (int)(d * (high - low + 1));
 return(low + k);
}

Thank you.... 

J.

--
KonkyFong


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: convert INT to CHAR but print's BEEP...
  2003-11-12  4:35     ` convert INT to CHAR but print's BEEP J.
@ 2003-11-12  7:11       ` Mikael Aronsson
  2003-11-13  1:26         ` convert INT to CHAR - SOLVED J.
  2003-11-13  6:36       ` convert INT to CHAR but print's BEEP Jeff Woods
  1 sibling, 1 reply; 19+ messages in thread
From: Mikael Aronsson @ 2003-11-12  7:11 UTC (permalink / raw)
  To: linux-c-programming

Hi !

The problem with strcat is that you cannot just use a pointer to the
character because all C string functions require that you end the string
with a zero (0) byte.

You could do something like this for eample:
char temp[ 2];
temp[ 0] = my_character;
temp[ 1] = '\0';
strcat( org_string, temp);

Mikael

----- Original Message ----- 
From: "J." <mailing-lists@xs4all.nl>
To: <linux-c-programming@vger.kernel.org>
Sent: Wednesday, November 12, 2003 5:35 AM
Subject: convert INT to CHAR but print's BEEP...


> Wednesday, November 12 05:19:21
>
> Hello, I have kind of a problem with converting an int to a char.
> The get_rand_str() function returns an string build of random
> charaters with a max length of int `MAX'.
>
> This seems to work at first glance:
> ~: ./program
> qqxfrd
>
> However if I examen the output closer:
> ~: ./program | od -a
> 0000000   q   q soh   x stx   f etx   r eot   d enq  nl
> 0000014
>
> Now I know why my computer keeps beeping everytime it
> outputs a string :-)
>
> What is the correct way of changing the int value to a
> char value so that I can append it to the return string ?
>
> char *get_rand_str(int max) {
>  int i = 0;
>  char value;
>  char *retval = NULL;
>
>  for(; i < max; i++) {
>   value = get_ascii_code(97, 122);
>   retval = (char *)realloc(retval, sizeof(char));
>   strcat(retval, &value);
>  }
>
>  return retval;
>  free(retval);
> }
>
> int get_ascii_code(int low, int high) {
>  int k = 0;
>  double d = 0;
>
>  d = (double)rand() / ((double)RAND_MAX + 1);
>  k = (int)(d * (high - low + 1));
>  return(low + k);
> }
>
> Thank you....
>
> J.
>
> --
> KonkyFong
>
> -
> To unsubscribe from this list: send the line "unsubscribe
linux-c-programming" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: convert INT to CHAR - SOLVED....
  2003-11-12  7:11       ` Mikael Aronsson
@ 2003-11-13  1:26         ` J.
  0 siblings, 0 replies; 19+ messages in thread
From: J. @ 2003-11-13  1:26 UTC (permalink / raw)
  To: linux-c-programming

On Wed, 12 Nov 2003, Mikael Aronsson wrote:
> Hi !
> 
> The problem with strcat is that you cannot just use a pointer to the
> character because all C string functions require that you end the string
> with a zero (0) byte.
> 
> You could do something like this for eample:
> char temp[ 2];
> temp[ 0] = my_character;
> temp[ 1] = '\0';
> strcat( org_string, temp);
> 
> Mikael

THnkx.. I fixed that, and I allocated the return value with calloc, this 
works ... :)

I learnend something again....

Thnkx

J.

--
FOnkTong


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: convert INT to CHAR but print's BEEP...
  2003-11-12  4:35     ` convert INT to CHAR but print's BEEP J.
  2003-11-12  7:11       ` Mikael Aronsson
@ 2003-11-13  6:36       ` Jeff Woods
  1 sibling, 0 replies; 19+ messages in thread
From: Jeff Woods @ 2003-11-13  6:36 UTC (permalink / raw)
  To: J.; +Cc: linux-c-programming

At 11/12/2003 05:35 AM +0100, J. wrote:
>Hello, I have kind of a problem with converting an int to a char. The 
>get_rand_str() function returns an string build of random charaters with a 
>max length of int `MAX'.

I'm sure there are faster algorithms, but how about something simple like:

#include <stdlib.h>

typedef unsigned char   U8;
typedef unsigned short  U16;

/* Set <buf_len> bytes at <buf> to random values from <low> to <high>. */
void set_rand_buf(char *buf, size_t buf_len, U8 low, U8 high) {
     U8 range = high - low + 1;
     while (buf_len--)
         *buf++ = low + (U8)((range*rand())/(RAND_MAX+1.0));
}

/* Sample calls */

#include <assert.h>

int main(void) {
     char        buf[80];
     size_t      k;

EXAMPLE_1:
     /* Completely fill buf with random data; may include embedded nulls */
     set_rand_buf(buf, sizeof buf, 0, 255);
     for (k = 0; k < sizeof buf; k++)
         printf("byte[%3d]=%3hu\n", k, (U16)buf[k]);

EXAMPLE_2:
     set_rand_buf(buf, 50, '0', '9');    /* Get 50 random ASCII digits. */
     buf[50] = 0;        /* Null-terminate the string. */
     printf("50 digits: %s\n", buf);

EXAMPLE_3:
     set_rand_buf(buf, 26, 'a', 'z');    /* Get 26 random lower-case 
letters. */
     buf[26] = 0;        /* Null-terminate the string. */
     printf("26 letters: %s\n", buf);

EXAMPLE_4:
#DEFINE LEN 27
     /* Get LEN random hex digits in ASCII */
     assert(LEN < sizeof buf);
     set_rand_buf(buf, LEN, 0, 15);      /* First get LEN hex values */
     {   /* Convert hex values from binary to ASCII */
         char *ptr = buf + LEN;
         while (ptr-- > buf)
             *ptr = (*ptr >= 10) ? ('a' - 10 + *ptr) : ('0' + *ptr);
     }
     buf[LEN] = 0;       /* Null-terminate as a string. */
     printf("hex digits %s\n", buf);


     return 0;   /* No-error program exit */
}

P.S.  The above code has never been compiled, so there may be all kinds of 
typos or other errors present.

--
Jeff Woods <kazrak+kernel@cesmail.net> 



^ permalink raw reply	[flat|nested] 19+ messages in thread

* mixing C/C++
@ 2003-11-24 11:10 Elias Athanasopoulos
  2003-11-24 12:18 ` Steven Shaw
  2003-11-24 18:44 ` Dari'o Mariani
  0 siblings, 2 replies; 19+ messages in thread
From: Elias Athanasopoulos @ 2003-11-24 11:10 UTC (permalink / raw)
  To: linux-c-programming

Hello!

Consider:

class Bar {
public:
  Bar();
  ~Bar();

  void dump2(void);
};

class Foo : public Bar {
public:
	Foo();
	~Foo();

	void dump(void);
};

extern "C"
Foo * wrap_foo_ctor()
{
	return new Foo();
}

extern "C"
void wrap_foo_dump(Foo *f)
{
	f->dump();
}

extern "C"
void wrap_bar_dump2(Bar *b)
{
	b->dump2();
}

Now, I have a C program:

int main(void)
{
	struct Foo *f;

	f = wrap_foo_ctor();
	wrap_foo_dump(f);
	wrap_bar_dump2(f);
}

which is working as -at least- I expect. Bar::dump2() is 
called since Foo inherits from Bar.

However is it correct? I have a larger C++ project, which I'm
creating wrappers for in C, and I get a segfault in a similar
case (i.e. when I call a method *deep* inside the inheritence tree of a 
class). 

Regards,
-- 
Elias Athanasopoulos
http://www.pcmag.gr - Libecom S.A.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: mixing C/C++
  2003-11-24 11:10 mixing C/C++ Elias Athanasopoulos
@ 2003-11-24 12:18 ` Steven Shaw
  2003-11-24 17:55   ` Elias Athanasopoulos
  2003-11-24 18:44 ` Dari'o Mariani
  1 sibling, 1 reply; 19+ messages in thread
From: Steven Shaw @ 2003-11-24 12:18 UTC (permalink / raw)
  To: linux-c-programming

On Monday 24 November 2003 21:10, Elias Athanasopoulos wrote:
> Now, I have a C program:
>
> int main(void)
> {
> 	struct Foo *f;
>
> 	f = wrap_foo_ctor();
> 	wrap_foo_dump(f);
> 	wrap_bar_dump2(f);
> }

Looks fine to me.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: mixing C/C++
  2003-11-24 12:18 ` Steven Shaw
@ 2003-11-24 17:55   ` Elias Athanasopoulos
  2003-11-25  2:21     ` Steven Shaw
  0 siblings, 1 reply; 19+ messages in thread
From: Elias Athanasopoulos @ 2003-11-24 17:55 UTC (permalink / raw)
  To: Steven Shaw; +Cc: linux-c-programming

On Mon, Nov 24, 2003 at 10:18:40PM +1000, Steven Shaw wrote:
> On Monday 24 November 2003 21:10, Elias Athanasopoulos wrote:
> > Now, I have a C program:
> >
> > int main(void)
> > {
> > 	struct Foo *f;
> >
> > 	f = wrap_foo_ctor();
> > 	wrap_foo_dump(f);
> > 	wrap_bar_dump2(f);
> > }
> 
> Looks fine to me.

Apparently it is fine. The problem occures when I am wrapping
a class which inherits from multiple classes with virtual
functions. 

Any workarounds? 

Regards,
-- 
University of Athens			I bet the human brain 
Physics Department				is a kludge --Marvin Minsky 

	

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: mixing C/C++
  2003-11-24 11:10 mixing C/C++ Elias Athanasopoulos
  2003-11-24 12:18 ` Steven Shaw
@ 2003-11-24 18:44 ` Dari'o Mariani
  1 sibling, 0 replies; 19+ messages in thread
From: Dari'o Mariani @ 2003-11-24 18:44 UTC (permalink / raw)
  To: Elias Athanasopoulos; +Cc: linux-c-programming

Hello:
   I think that the problem is in

extern "C"
Foo * wrap_foo_ctor()
{
	return new Foo();
}

In your C program you are using a C++ construct inside C, wich may work 
but the C compiler doesn't understand virtual functions so it might be 
confused there.

Elias Athanasopoulos wrote:
> Hello!
> 
> Consider:
> 
> class Bar {
> public:
>   Bar();
>   ~Bar();
> 
>   void dump2(void);
> };
> 
> class Foo : public Bar {
> public:
> 	Foo();
> 	~Foo();
> 
> 	void dump(void);
> };
> 
> extern "C"
> Foo * wrap_foo_ctor()
> {
> 	return new Foo();
> }
> 
> extern "C"
> void wrap_foo_dump(Foo *f)
> {
> 	f->dump();
> }
> 
> extern "C"
> void wrap_bar_dump2(Bar *b)
> {
> 	b->dump2();
> }
> 
> Now, I have a C program:
> 
> int main(void)
> {
> 	struct Foo *f;
> 
> 	f = wrap_foo_ctor();
> 	wrap_foo_dump(f);
> 	wrap_bar_dump2(f);
> }
> 
> which is working as -at least- I expect. Bar::dump2() is 
> called since Foo inherits from Bar.
> 
> However is it correct? I have a larger C++ project, which I'm
> creating wrappers for in C, and I get a segfault in a similar
> case (i.e. when I call a method *deep* inside the inheritence tree of a 
> class). 
> 
> Regards,



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: mixing C/C++
  2003-11-24 17:55   ` Elias Athanasopoulos
@ 2003-11-25  2:21     ` Steven Shaw
  2003-11-25 10:49       ` elathan
  0 siblings, 1 reply; 19+ messages in thread
From: Steven Shaw @ 2003-11-25  2:21 UTC (permalink / raw)
  To: Elias Athanasopoulos; +Cc: linux-c-programming

On Tuesday 25 November 2003 03:55, Elias Athanasopoulos wrote:
> On Mon, Nov 24, 2003 at 10:18:40PM +1000, Steven Shaw wrote:
> > On Monday 24 November 2003 21:10, Elias Athanasopoulos wrote:
> > > Now, I have a C program:
> > >
> > > int main(void)
> > > {
> > > 	struct Foo *f;
> > >
> > > 	f = wrap_foo_ctor();
> > > 	wrap_foo_dump(f);
> > > 	wrap_bar_dump2(f);
> > > }
> >
> > Looks fine to me.
>
> Apparently it is fine. The problem occures when I am wrapping
> a class which inherits from multiple classes with virtual
> functions.

That should be fine too.

> Any workarounds?

Maybe you have C++ code with static members. If so you need to compile main() 
with a C++ compiler. Here is an excellent resource:

	http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html

Also the C++ FAQ Lite main page now has a Google-based sitesearch box:

	http://www.parashift.com/c++-faq-lite/

Steve.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: mixing C/C++
  2003-11-25  2:21     ` Steven Shaw
@ 2003-11-25 10:49       ` elathan
  2003-11-25 11:42         ` Glynn Clements
  2003-11-25 16:32         ` Steven Shaw
  0 siblings, 2 replies; 19+ messages in thread
From: elathan @ 2003-11-25 10:49 UTC (permalink / raw)
  To: Steven Shaw; +Cc: linux-c-programming

[-- Attachment #1: Type: text/plain, Size: 1070 bytes --]

Quoting Steven Shaw <steven_shaw@iprimus.com.au>: 
 
> On Tuesday 25 November 2003 03:55, Elias Athanasopoulos wrote: 
> > Apparently it is fine. The problem occures when I am wrapping 
> > a class which inherits from multiple classes with virtual 
> > functions. 
>  
> That should be fine too. 
>  
> > Any workarounds? 
>  
> Maybe you have C++ code with static members. If so you need to compile 
main() 
>  
> with a C++ compiler. Here is an excellent resource: 
>  
> 	http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html 
 
This is what I read and came to the above conclusion. 
 
It states (32.9): 
 
You can safely access a C++ object's data from a C function if the C++ class:  
 
Has no virtual functions (including inherited virtual functions) 
  
So I guess that is a problem. I verified that with the attached source file. Compile 
the lib.cxx as a shared libfoo.so file and then try to call f->dump3() (f is struct 
*Foo).   
 
Also, I don't have main() in my project since it is a shared library. 
 
Thanks for your help. 
 
Regards, 
Elias 
 
  

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: lib.cxx --]
[-- Type: text/x-c++src; name="lib.cxx", Size: 716 bytes --]


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

class Taz {
public:
  Taz();
  ~Taz();

  virtual void dump3(void);
};

class Bar {
public:
  Bar();
  ~Bar();

  virtual void dump2(void);
};

class Foo : public Bar, public Taz{
public:
	Foo();
	~Foo();

	void dump(void);
};

Foo::Foo()
{
}

void Foo::dump(void)
{
	printf("Foo Hello!\n");
}

Bar::Bar()
{
}

Bar::~Bar()
{
}

void Bar::dump2(void)
{
	printf ("Bar Hello\n");
}

Taz::Taz()
{
}

void Taz::dump3(void)
{
	printf ("Taz Hello!\n");
}

extern "C"
Foo * wrap_foo_ctor()
{
	return new Foo();
}

extern "C"
void wrap_foo_dump(Foo *f)
{
	f->dump();
}

extern "C"
void wrap_bar_dump2(Bar *b)
{
	b->dump2();
}

extern "C"
void wrap_taz_dump3(Taz *t)
{
	t->dump3();
}


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: mixing C/C++
  2003-11-25 10:49       ` elathan
@ 2003-11-25 11:42         ` Glynn Clements
  2003-11-25 13:12           ` elathan
  2003-11-25 16:32         ` Steven Shaw
  1 sibling, 1 reply; 19+ messages in thread
From: Glynn Clements @ 2003-11-25 11:42 UTC (permalink / raw)
  To: elathan; +Cc: Steven Shaw, linux-c-programming


elathan@phys.uoa.gr wrote:

> > > Apparently it is fine. The problem occures when I am wrapping 
> > > a class which inherits from multiple classes with virtual 
> > > functions. 
> >  
> > That should be fine too. 
> >  
> > > Any workarounds? 
> >  
> > Maybe you have C++ code with static members. If so you need to compile main() 
> >  
> > with a C++ compiler. Here is an excellent resource: 
> >  
> > 	http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html 
>  
> This is what I read and came to the above conclusion. 
>  
> It states (32.9): 
>  
> You can safely access a C++ object's data from a C function if the C++ class:  
>  
> Has no virtual functions (including inherited virtual functions) 
>   
> So I guess that is a problem.

Not for you. You aren't trying to access an object's data (member
variables) from a C function. The only C function in your original
example was main(), and that doesn't access an object's data. All of
the other functions are C++ functions; some of them have C linkage
(extern "C"), but they are still C++ functions.

> I verified that with the attached source file. Compile 
> the lib.cxx as a shared libfoo.so file and then try to call f->dump3() (f is struct 
> *Foo).   

It works fine for me:

	$ g++ -c -Wall lib.cxx 
	lib.cxx:5: warning: `class Taz' has virtual functions but non-virtual 
	   destructor
	lib.cxx:13: warning: `class Bar' has virtual functions but non-virtual 
	   destructor
	lib.cxx:21: warning: `class Foo' has virtual functions but non-virtual 
	   destructor
	$ g++ -shared -o libfoo.so lib.o 
	$ gcc -c -Wall foo.c
	$ gcc foo.o -L. -lfoo
	$ LD_LIBRARY_PATH=. ./a.out 
	Foo Hello!
	Bar Hello
	$ cat foo.c
	
	extern void *wrap_foo_ctor(void);
	extern void wrap_foo_dump(void *);
	extern void wrap_bar_dump2(void *);
	extern void wrap_taz_dump3(void *);
	
	int main(void)
	{
		void *f;
	
		f = wrap_foo_ctor();
		wrap_foo_dump(f);
		wrap_bar_dump2(f);
	
		return 0;
	}


> Also, I don't have main() in my project since it is a shared library. 

If you're getting a segfault, you are running a program, and that
program has a main() function.

In any case, I'm not sure that the comment about compiling main() with
a C++ compiler is applicable to using C++ shared libraries on Linux. 
There are plenty of shared libraries which are written in C++ but are
usable from C programs without special treatment (GLU is probably the
most common example).

-- 
Glynn Clements <glynn.clements@virgin.net>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: mixing C/C++
  2003-11-25 11:42         ` Glynn Clements
@ 2003-11-25 13:12           ` elathan
  2003-11-26  2:09             ` Glynn Clements
  0 siblings, 1 reply; 19+ messages in thread
From: elathan @ 2003-11-25 13:12 UTC (permalink / raw)
  To: Glynn Clements; +Cc: Steven Shaw, linux-c-programming

Quoting Glynn Clements <glynn.clements@virgin.net>: 
> It works fine for me: 
[snipped] 
> 		wrap_foo_dump(f); 
> 		wrap_bar_dump2(f); 
> 	 
> 		return 0; 
> 	} 
 
Up to that point yes. But if you try to call dump3() (exactly with the code you 
have pasted) you wan't get "Taz Hello", but "Bar Hello". This strange behaviour 
will not happen, if you subistute the virtual methods with ordinary ones. 
 
Regards, 
Elias 
 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: mixing C/C++
  2003-11-25 10:49       ` elathan
  2003-11-25 11:42         ` Glynn Clements
@ 2003-11-25 16:32         ` Steven Shaw
  1 sibling, 0 replies; 19+ messages in thread
From: Steven Shaw @ 2003-11-25 16:32 UTC (permalink / raw)
  To: elathan; +Cc: linux-c-programming

On Tuesday 25 November 2003 20:49, you wrote:
> Also, I don't have main() in my project since it is a shared library.

Do make sure that you link with g++ (as Glynn did in his example). It will 
take care of a special linker script that collects all the static 
initialisations and I think there may be some magic functions that get 
collected for exception handling too.

If that fails why don't you post a complete minimal example that coredumps or 
just your original code that's coredumping if necessary.

Steve.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: mixing C/C++
  2003-11-25 13:12           ` elathan
@ 2003-11-26  2:09             ` Glynn Clements
  2003-12-02 18:22               ` Elias Athanasopoulos
  0 siblings, 1 reply; 19+ messages in thread
From: Glynn Clements @ 2003-11-26  2:09 UTC (permalink / raw)
  To: elathan; +Cc: Steven Shaw, linux-c-programming


elathan@phys.uoa.gr wrote:

> > It works fine for me: 
> [snipped] 
> > 		wrap_foo_dump(f); 
> > 		wrap_bar_dump2(f); 
> > 	 
> > 		return 0; 
> > 	} 
>  
> Up to that point yes. But if you try to call dump3() (exactly with the code you 
> have pasted) you wan't get "Taz Hello", but "Bar Hello". This strange behaviour 
> will not happen, if you subistute the virtual methods with ordinary ones. 

Right.

You cannot treat "Foo*" and "Taz*" as equivalent within C.

You would have to have separate wrap_foo_dump3() and wrap_taz_dump3(),
and pass only Foo* to the former and only Taz* to the latter.

With single inheritance, the subclass' data structure normally begins
with the (sole) superclass' data structure, with any subclass-specific
fields appended afterwards. With multiple inheritance, this isn't
possible; the beginning of the subclass' data structure cannot
simultaneously match those for multiple superclasses.

A C++ compiler will adjust the pointer when performing a narrowing
cast, so it points directly at the superclass' data structure. A C
compiler can't do this, as it doesn't know anything about classes.

This issue is touched upon at the bottom of §32.8 of the FAQ to which
Steven linked:

	http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html#faq-32.8

-- 
Glynn Clements <glynn.clements@virgin.net>
-
To unsubscribe from this list: send the line "unsubscribe linux-c-programming" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: mixing C/C++
  2003-11-26  2:09             ` Glynn Clements
@ 2003-12-02 18:22               ` Elias Athanasopoulos
  0 siblings, 0 replies; 19+ messages in thread
From: Elias Athanasopoulos @ 2003-12-02 18:22 UTC (permalink / raw)
  To: Glynn Clements; +Cc: Steven Shaw, linux-c-programming

On Wed, Nov 26, 2003 at 02:09:52AM +0000, Glynn Clements wrote:
> > Up to that point yes. But if you try to call dump3() (exactly with the code you 
> > have pasted) you wan't get "Taz Hello", but "Bar Hello". This strange behaviour 
> > will not happen, if you subistute the virtual methods with ordinary ones. 

Thank you both for your detailed replies. My apologies for
my delayed answer.

Regards,
-- 
University of Athens			I bet the human brain 
Physics Department				is a kludge --Marvin Minsky 

	

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2003-12-02 18:22 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-11-08  9:30 mixing C/C++ Elias Athanasopoulos
2003-11-08 13:36 ` James Stevenson
2003-11-10 15:00 ` Matthew Studley
2003-11-10 17:37   ` Elias Athanasopoulos
2003-11-12  4:35     ` convert INT to CHAR but print's BEEP J.
2003-11-12  7:11       ` Mikael Aronsson
2003-11-13  1:26         ` convert INT to CHAR - SOLVED J.
2003-11-13  6:36       ` convert INT to CHAR but print's BEEP Jeff Woods
  -- strict thread matches above, loose matches on Subject: below --
2003-11-24 11:10 mixing C/C++ Elias Athanasopoulos
2003-11-24 12:18 ` Steven Shaw
2003-11-24 17:55   ` Elias Athanasopoulos
2003-11-25  2:21     ` Steven Shaw
2003-11-25 10:49       ` elathan
2003-11-25 11:42         ` Glynn Clements
2003-11-25 13:12           ` elathan
2003-11-26  2:09             ` Glynn Clements
2003-12-02 18:22               ` Elias Athanasopoulos
2003-11-25 16:32         ` Steven Shaw
2003-11-24 18:44 ` Dari'o Mariani

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).