分类: C/C++
2006-06-23 13:26:32
==============================================================================
Interfacing C code with C++.
Name: Brent York
Handle: The Dragon (ThaDragon on IRC)
Email: york@nbnet.nb.ca
Affils: Coder for Nuclear Winter Entertainment
Coder for Spheringer technologies.
Coder for Henry and York Development "Development with thought."
Editor of Cscene Magazine
Organizer of the OS Developers Information Network (ODIN).
==============================================================================
C++ is a wonderful language, and most if not all things that you can
write in C you can write in C++ as well. Unfortunately however there
comes a time where you come accross some of your old C code that you
wrote way back when that you dont want to have to rewrite or restructure
for your current code.
Seeing as to how one big plus of programming properly is code
reusability which is a great thing and speeds up development times.
However one of the main problems between multilanguage interfacing is
that no two languages ever call functions or pass parameters the same way.
This of course can be a PITA. This document (I hope) will show
you how to solve this problem for multilanguage programming using C and C++
together.
===========
The Dilemma
===========
The main problem (so I hear) with interfacing with C++ is that it
mangles function names. The reasons for this are things such as overloaded
functions, destructors and constructors etc. We wont go into the guts of
writing a C++ compiler here because it probably isn't needed.
All you need to realise is that C doesn't mangle function names
and therefore C++ (expecting the mangling) cant find them. This causes a
problem not necessarily when compiling but CERTAINLY when linking.
==============================================
Extern, a declaration of an external "object".
==============================================
So now we have great fun, and learn a way to declare externals.
You might ask what extern has to do with interfacing C with C++, and we
wont get into it just yet (hay I have to fill my article quota ;}), but
we will in the next section.
Extern is used for declaring external data or functions, and can
be used in a block format to encompass many things at once or in a single
line format to only encompass one thing.
Then the compiler sees extern it allows the use of the external
reference in your code, but makes the linker look for the external at
linking time.
This is a great boon for things like global variables (yuck), but is
rarely used to declare functions external because they are implicitly
external. That is to say the compiler knows that they are extern.
However, this isn't the case as you will soon see, when interfacing
C++ with C. (Wow, a rhyme =})
The syntax of extern is:
extern ["C"] [{] Things to declare external [[}] || [;]]
All things in []'s are optional, except for the || (or obviously) which
means that you either have to close off your { with a } if you used that,
or you can use ; in a single line.
Example of a single line extern declaration
extern int myGVar;
Example of a multi line extern declaration
extern {
int myGVar;
int yourGVar;
int everyBodysGVar;
}
==============================
The cure for function mangling
==============================
The cure of course as you may have noticed is the "C" optional
in the extern declaration's syntax. In the .h file you include in your
C++ all functions and global data you want to use in your C++ program
should be declared extern "C".
That is to say that youll have to have two .h files, one for
your C source (which should NOT be extern "C") and one for the C++ source
that holds the function prototypes and global variables for the C source,
all declared extern "C".
An example follows:
--------------------------use_c.c----------------------------
#include
#include "use_c_c.h" /* C header for C file */
void printme(void) {
printf("Hello from C!\n");
}
-------------------------use_c_c.h----------------------------
/* C header for use_c.c */
#ifndef __CPP_USE_C_C_HDR__
#define __CPP_USE_C_C_HDR__
void printme(void);
#endif
-------------------------use_cpp.hh----------------------------
// C++ header for use_c.c so we can use it with our c++ program
#ifndef __CPP_USE_C_CPP_HDR__
#define __CPP_USE_C_CPP_HDR__
extern "C" void printme(void);
#endif
-------------------------use_cpp.cc----------------------------
// C++ main function that uses use_c's printme() function.
#include
#include "use_cpp.h"
int main(void) {
printme();
return 0;
}
---------------------------------------------------------------
Of course, this is a simple example, but the same holds true for global
data, and all functions you must use. to save space and make it more
readable you can use a blocked extern. But ALL THINGS that you must
access from the .c file such as functions and data MUST be declared extern.
Compile the above program and run it with prettymuch any compiler and
youll get the intended output.
Note however that you MUST compile the .c file with a C compiler, not a
C++ compiler, and you MUST compile the .cc file with a .cc compiler.
===============
Finishing words
===============
All in all interfacing C with C++ isn't that hard, infact its the
easiest task that one can come accross with multilanguage programming.
All you have to remember is the extern keyword and all is set.
And now you have the knowlege to take it even further and be able to
reuse your C code in your C programs without changes, isn't that great?
Have fun, and most of all, contribute!
The Dragon
You can download a zipfile of the source in this document