[gnu.g++.help] Combination of C and C++

eggberd@.uni-paderborn.de (Bernd Eggert) (02/12/91)

This message is posted for someone who cannot post to the net himself.

Please respond to the net or to axel@cadlab.cadlab.de !

-------------------------------------------------------------
I have a question concerning the combination of C and C++.


Assume the following situation:

You want to write a library in C++. People working with your library should be
able to use it either from C++ or from C.

In order to make functions callable from C you use the 'extern "C"' directive.
With this directive you can write ordinary C functions 'around' the C++
objects. These functions can be called from a C program.

The problem occurs when you try to link the C program with the C++ library.
The normal linker does not care for constructors or destructors and therefore
static objects will not be initialized.

Is there an elegant and portable way to solve this problem? We are interested
in solutions for AT&T CC and g++.

Below is an example which works if you use the C++-linker (but not with
a normal linker)

Thanks for any help.

-------------------------------------------------------------------------------
File 'hello.C':
-------------------------------------------------------------------------------

/* this is a C++ class to be used by a C program */

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


class hello
{
    private:
      char name[20];

    public:
      hello(char *n)
      {
        strcpy(name,n);
      }

      void print()
      {
        cout << "Hello " << name << "\n"; /* cout requires initialization */
        printf("Hello %s\n",name);        /* printf is no problem */
      }
};


/* these functions enable the non-C++-user to use the class 'hello': */

extern "C"
{

void *create_person(char *n)
{
    return((void *)new hello(n));
}

void print_person(void *p)
{
    ((hello *)p)->print();
}

}

-------------------------------------------------------------------------------
File 'chello.c'
-------------------------------------------------------------------------------

/* this is a C program dealing with a C++ object */


void *create_person(char *n);
void print_person(void *p);


main()
{
    void *p;

    __main(); /* this is necessary for initializing static objects in g++ */

    p = create_person("Henry");

    print_person(p);
}

-------------------------------------------------------------------------------
File 'makefile':
-------------------------------------------------------------------------------

chello: chello.o hello.o
        g++ -o chello chello.o hello.o

chello.o: chello.c
        gcc -c chello.c

hello.o: hello.C
        g++ -c hello.C


-------------------------------------------------------------------------------
Axel Meckenstock                            CADLAB
                                            University of Paderborn
phone : +49 5251 284-120                    Siemens Nixdorf Information Systems
fax   : +49 5251 284-140                    Bahnhofstr. 32
email : axel@cadlab.cadlab.de               D-4790 Paderborn
-------------------------------------------------------------------------------

don@zardoz.coral.com (Don Dewar) (02/21/91)

) Resent-From: uunet!ai.mit.edu!gnulists
) Return-Path: <gnulists@ai.mit.edu>
) Resent-Date: 12 Feb 91 15:10:07 GMT
) Date: 12 Feb 91 15:10:07 GMT
) From: uunet!.uni-paderborn.de!eggberd  (Bernd Eggert)
) Sender: uunet!ai.mit.edu!gnulists
) Organization: Uni-GH Paderborn, West Germany
) Subject: Combination of C and C++
) To: help-g++@prep.ai.mit.edu
) 
) 
) This message is posted for someone who cannot post to the net himself.
) 
) Please respond to the net or to axel@cadlab.cadlab.de !
) 
) -------------------------------------------------------------
) I have a question concerning the combination of C and C++.
) 
) 
) Assume the following situation:
) 
) You want to write a library in C++. People working with your library should be
) able to use it either from C++ or from C.
) 
) In order to make functions callable from C you use the 'extern "C"' directive.
) With this directive you can write ordinary C functions 'around' the C++
) objects. These functions can be called from a C program.
) 
) The problem occurs when you try to link the C program with the C++ library.
) The normal linker does not care for constructors or destructors and therefore
) static objects will not be initialized.
) 
) Is there an elegant and portable way to solve this problem? We are interested
) in solutions for AT&T CC and g++.
) 
) Below is an example which works if you use the C++-linker (but not with
) a normal linker)
) 
) Thanks for any help.
) 
) -------------------------------------------------------------------------------
) File 'hello.C':
) -------------------------------------------------------------------------------
) 
) /* this is a C++ class to be used by a C program */
) 
) #include <stream.h>
) #include <string.h>
) #include <stdio.h>
) 
) 
) class hello
) {
)     private:
)       char name[20];
) 
)     public:
)       hello(char *n)
)       {
)         strcpy(name,n);
)       }
) 
)       void print()
)       {
)         cout << "Hello " << name << "\n"; /* cout requires initialization */
)         printf("Hello %s\n",name);        /* printf is no problem */
)       }
) };
) 
) 
) /* these functions enable the non-C++-user to use the class 'hello': */
) 
) extern "C"
) {
) 
) void *create_person(char *n)
) {
)     return((void *)new hello(n));
) }
) 
) void print_person(void *p)
) {
)     ((hello *)p)->print();
) }
) 
) }
) 
) -------------------------------------------------------------------------------
) File 'chello.c'
) -------------------------------------------------------------------------------
) 
) /* this is a C program dealing with a C++ object */
) 
) 
) void *create_person(char *n);
) void print_person(void *p);
) 
) 
) main()
) {
)     void *p;
) 
)     __main(); /* this is necessary for initializing static objects in g++ */
) 
)     p = create_person("Henry");
) 
)     print_person(p);
) }
) 
) -------------------------------------------------------------------------------
) File 'makefile':
) -------------------------------------------------------------------------------
) 
) chello: chello.o hello.o
)         g++ -o chello chello.o hello.o
) 
) chello.o: chello.c
)         gcc -c chello.c
) 
) hello.o: hello.C
)         g++ -c hello.C
) 
) 
) -------------------------------------------------------------------------------
) Axel Meckenstock                            CADLAB
)                                             University of Paderborn
) phone : +49 5251 284-120                    Siemens Nixdorf Information Systems
) fax   : +49 5251 284-140                    Bahnhofstr. 32
) email : axel@cadlab.cadlab.de               D-4790 Paderborn
) -------------------------------------------------------------------------------
) 
) 
) 
) 

In the case of g++, you must use the g++ linker.  I don't find that
particularly unportable, just a little inconvenient for those persons
that want to link with you library and don't have the linker.  In the
case of CFront, I don't think you have a problem.  CFront just creates
"C" code that is compiled and should act just like a normal "C"
program with name mangling.

I would point out, however, that distributing C++ binary libraries can
be a problem in general for a couple of reasons.  If the user wants to
add to the library, they may want to add a new virtual function at a
root class, which throws off the virtual tables.  The user must use
the C++ compiler used to generate the libraries if they are linking in
more C++ code that calls the library, because the name mangling scheme
between the two compilers is likely to be different.

I just thought I might pass that on to you.  Good luck!


  +---------+
  | Coral   |
  |@@@@@*@**|
  |@@*@@**@@|     Don Dewar
  |*@@**@@@@|     Coral Network Corporation, Marlborough, MA
  |@***@@@@@|     Internet: don@coral.com
  |@@**@@@@@|     Phone:    (508) 460-6010
  |*********|     Fax:      (508) 481-6258
  |Networks |
  +---------+

jj00@eurotherm.co.uk (John Juer) (02/27/91)

(I can't reach axel@cadlab.cadlab.de)

If you are using a C++ library, use "collect" to create an object file
with the constructor/destructor bits and put it in the library. The
the C linker should pick it up.

jj00@uk.co.eurotherm