Back to ObjectValue Logo articles

         Linking C with C++

Immo Hüneke

1          Introduction

When developing applications in C++, the need sometimes arises to call C++ functions from sections of C code. Examples include:

          where a section of the program is written in assembler, because it has to be ultra fast or handles raw interrupts. It is far easier to call C than C++ from assembler

          where a GUI builder such as UIMX or TeleUse has been used, which requires the screen designer to type the names of C functions which are then linked as callbacks to the displayed widgets

          where a utility or system library contains hooks for “user exits” which the library expects to be provided as C code.

This short application note suggests a method for providing such linkage. The basic facility has been tried out with R2.1 of cfront and with Zortech C++, so it should be portable across all compilers.

2          R2.1 Support for Inter-Language Linking

Release 2.1 of C++ has a defined syntax for calling C functions from C++ code[3]. This was introduced to permit function name overloading in C++ to work properly, which had the unintended side effect of disabling the calling of external C functions. To defeat this effect, the programmer has to define the type of linkage on the extern declaration:

extern "C"

{

        int open (char* path, int oflag, int mode = 0xFFF);

        int close (int fd);

        int write (int fd, char* buf, unsigned nbytes);

        int read (int fd, char* buf, unsigned nbytes);

}

If you left off the “extern C” part of the declaration, the compiler would assume that the external functions referenced were C++ (this is the default). C++ compilers perform name mangling by incorporating the argument types into function names, so that overloaded names are disambiguated. Since the compiler cannot know which names might be overloaded in another compilation unit, it always mangles all function names, unless explicitly instructed not to in the manner shown above.

By contrast, before Release 2 the programmer had to enable function name overloading explicitly, using the “overload” keyword. For compatibility, this keyword is still allowed but has no effect.

It is a little known fact that the “extern C” declaration works equally well for functions defined within the C++ module. Once the compiler has been instructed that a particular function is not overloaded and should not be mangled, it continues to apply this rule if it encounters a definition for the function. You can therefore write functions with C linkage and compile them using the C++ compiler.

This is all you actually need to be able to call C++ from C. The following section suggests some guidelines about the use of this feature in a fashion that is compatible with object oriented programming.

3          Linking C to C++ Objects

There’s no way in which you can declare C linkage for member functions of classes. Therefore the only way to call them from C is to go via a non-member function as intermediary. This is referred to as a “glue function”. However, you definitely don’t want to write a separate glue function for every member function of every object that might ever get called, so how can you achieve this interface efficiently?

The answer is to parameterize. The maximum number of glue functions that is required is the number of logically distinct functions that need to be called from C (or assembler). In the case of GUI builders, it will be the number of distinct function names that you have to type in. Usually this amounts to a different glue function for each class-member function that actually gets called from C.

An obvious parameter to use is an application-assigned object identifier. User interface management systems, for instance, usually provide a number to the program when they create a new window. This number identifies the window in subsequent interactions. When the UIMS notifies the number to your program, your program would create a new Window instance and associate it with the UIMS’s identifier.

A dictionary could be maintained to relate window identifiers to Window objects (dictionaries provide associative arrays and are described in [1] and [2]). Whenever your glue functions are called with a window identifier as an argument, they would first index the dictionary with the identifier to obtain a Window object reference. They would then call the appropriate member function, passing the remaining arguments from the UIMS. The dictionary would best be implemented as a static member of the Window class. For efficiency, client objects should be given direct access to the operations of the Dictionary, which implies that it must either be a public member of Window, or that Window must provide a public member function that returns a reference to it.

In some cases, member functions themselves can be treated as parameters to the glue functions. Typically, this would be in cases where the C code passes some form of op-code to the glue function. The op-code maps through a const static table to the appropriate member function of the target class.

You could even imagine a situation in which some sort of dispatcher object is used to maintain the association between the C subsystem (e.g. UIMS) and the C++ objects to which it interfaces. In this case, objects could reflect their current state by calling the dispatcher to alter the mapping from op-code to member function. Glue functions would call the dispatcher with the appropriate object ID and op-code arguments to invoke object operations. So the linkage would now consist of two intermediate components. In other words, you would have invented the C++ equivalent of epoxy resin glue!

            References

[1]       Stroustrup, B “The C++ Programming Language”. Addison-Wesley 1986.

[2]       Gorlen, KE, Orlow, SM, and Plexico, PS “Data Abstraction and Object-Oriented Programming in C++”. Wiley 1990.

[3]       Ellis, MA and Stroustrup, B “The Annotated C++ Reference Manual”. Addison-Wesley 1990.



Created Thu Oct 23 19:11:26 2003

Copyright ObjectValue Ltd.

Back to ObjectValue Logo articles