Mixing C and C Code in the Same Program
By Stephen Clamage, Sun Microsystems, Sun ONE Studio Solaris Tools Development Engineering
TRANSLATOR: Qiu Longbin
The C language provides a mixed code mechanism to compile the code to be compatible with C and C compilers in the same program. When you transplant the code to a different platform and compiler, you will experience different success. This article shows how to solve the general problems when you mix C, C . All situations in the article show what you want to do when using Sun C and C compilers. (Translation: GCC GCC and G are also a combination of this pair.)
content
-
Use a compatible compiler
-
In C
Source code Access C
Code
-
In c
Access C in the source code
Code
-
Mix iostream
And C
Standard I / O
-
Pointer with pointing functions
-
Use C
abnormal
-
Link program
Use a compatible compiler
The first requirement of the mixed code is that the C and C compilers you are using must be compatible. They must define basic types such as int, float, or pointers in the same way (for example). The Solaris operating system specifies the binary interface (ABI) of the application application of the C program, which contains information about how the basic type and functions are called. Any compiler available on the Solaris OS must follow ABI.
Sun C and C compilers follow Solaris OS ABI and are compatible. Third-party Solaris OS C compiler must also follow ABI. Any C compiler compatible with the Solaris OS is also compatible with the Sun C compiler.
By your
C
Compiler
C
Runtime library must also be the same
C
Compiler is compatible.
C
Standard
C
The runtime library is used as its subset, only a little bit different. in case
C
The compiler provides its own version
C
Head file, then the version of these headers is
C
It must also be compatible when used.
Sun C and C compilers use a compatible header file and use the same C operation time library. They are fully compatible.
in
C
Source code Access
C
Code
The C language provides a "linkage specification" that you can declare the function or object to follow the specific language program link agreement. The default link for objects and functions is C . All C compilers also provide C links for compatible C compilers.
When you need to access a function compiled with a C link (for example, a function is compiled by the C compiler), you must declare that the function has a C link (translation: in C code). Even if most C compilers have different links to C and C data objects, you also need to declare the C data object (Data Objects) in your C code. Type (Types) does not have a C or C link, in addition to the Pointer-to-function type of the function.
Disclaimer link specification
Use one of the following tags to declare an object or function has a language
LANGUAGE_NAME
the link to.
Extern "language_name" Declaration; extern "language_name" {declaration; decaration; ...} The first tag specifies that the declaration (or definition) has a language
LANGUAGE_NAME
Link agreement. The second marker specifies all of the curly brackets
LANGUAGE_NAME
the link to. Note that there should be a part number behind the last curly brackets of the second mark.
You can nested link specification, they did not create a range field (
Scope
). Consider the following example:
Extern "C" {void f (); // c linkage extern "C " {void g (); // C linkage extern "c" void h (); // c linkage void g2 (); // C linkage } Extern "C " Void K (); // C Linkage Void M (); // C Linkage}
All of the above functions are in the same all-local area, although nesting link specification.
In C code contains C header files If you want to use a C library, it defines the header files you want to prepare for the C compiler, you can include this header file in Extern "C":
Extern "C" {#include "header.h"}
WARNING-WARNING - This technology is not used for system header files on Solaris OS. Solaris header files, and all headers depends on Sun C and C compilers have been prepared for C and C compilers. If you specify a link, you may make the declaration of the declaration in the Solaris header file.
Create a header file of a mixed language (Mixed-languge)
If you want the header to be suitable for the C and C compilers, you may put all the declarations in the extern "C" curd, but the C compiler does not know these syntax. Each C compiler prefers the macro __cplusplus so you can use this macro defense C syntax extension:
#ifdef __cplusplus extern "C" {#ENDIF ... / * body of header * / #ifdef __cplusplus} / * Closing Brace for Extern "C" * / #ENDIF
Add C characteristics to c structs
Assume that you want to use the C library more easily in your C code. And assume that you don't use the C style access method, you may want to add member functions, or a virtual function, or may be derived from Class. How do you complete this transformation and make sure the C library function still recognizes your Struct? Consider the use of C's Struct BUF in this example:
/ * buf.h * /
struct buf {char * data; unsigned count;}; void buf_clear (struct buf *); int buf_print (struct buf *); / * return status, 0 means fail * / int buf_append (struct buf *, const char *, unsigned Count; / * Same return * / You want to transform this structure into C Class and do the changes below, making it easier:
Extern "C" {#include "buf.h"} class mybuf {// first Attempt - Will IT Work? public: mybuf (): data (0), count (0) {} void clear () {buf_clear (BUF *);} Bool Print () {Return BUF_PRINT ((BUF *) THIS);} Bool append (const char * p, unsigned c) {return buf_append ((buf *) THIS, P, C); } private: char * data; unsigned count;
The Class Mybuf interface seems to be more like C code, and more easily integrates the object-oriented programming - if it is feasible.
When the member function is transmitted
THIS
Pointer
BUF
What happened during the function?
C
Class layout
Layout
)match
C
Layout?
THIS
Pointer pointing to data members, or pointing
BUF
? If you increase the virtual function
Mybuf
What will it?
C standard has no guarantee for compatibility of BUF and Class MyBuf. The code here, there is no virtual function, you can work, but you can't expect this. If you add a virtual function, this code will fail because the compiler adds additional data (such as a pointer to the virtual table) to the beginning of the Class.
The portable solution is to put Struct BUF alone, although you want to protect data members and just provide access by member functions. You can guarantee C and C compatibility when you don't change the declaration.
You can send a C Class MyBUF from the C struct BUF and pass the pointer to the base class BUF to the member function of MyBuf. When converting myBuf * to BUF *, if the pointer to myBuf does not point to the beginning of BUF data, the C compiler will automatically adjust it. MyBUF's layout may change at C compile, but the C source code for manipulating MyBuf and BUF objects will work everywhere. The following example shows a portable method to add C and object-oriented features to C struct:
Extern "C" {#include "buf.h"} class mybuf: public buf {// a portable solution public: mybuf (): data (0), count (0) {} void clear () {} void clear () {} void clear () {} void clear () {} void clear () {} void clear () {} void clelectr (} Bool Print () {Return BUF_Print (this);} Bool append (const char * p, unsigned c) {return buf_append (this, p, c);}}; C
Code can be freely created and used
Mybuf
Object, pass them to those expectations
BUF
Objective
C
The code can be combined. Of course if you are
Mybuf
Added data members,
C
I don't know if the code is known. That is the consideration of the general design. You have to create and delete our hearts.
Delete
)
BUF
with
Mybuf
Object
.
yield
C
Code deletion
(Free)
A
C
The object created by the code is the safest and is not allowed
C
Code delete one
Mybuf
Object.
in
C
Source code Access
C
Code:
If you declare one
C
Function
C
Link, it can be
C
The compiler is called in a function. A statement has
C
Link function can use all
C
Features, if you want
C
Access it in the code, its parameters and return values must be
C
Accessible. For example, if a function declares a
Iostream
Class references as parameters, there is no (portable) method to parse this parameter type
C
translater.
C
Language is not referenced, template, or
C
charactermatic
Class.
Here is a
C
Linked
C
Example of functions:
#include
You can declare a function in the header file
, Was
C
with
C
Code shared:
#ifDef __cplusplus extern "C" #Endif Int Print (INT I, DOUBLE D);
You can record a function in the overloaded set as Extern "C" because a C function can only have a given name. If you want to access the overload function in C, you can write the C Wrapper function in different names, see the example below:
INT G (int); Double G; extern "C" INT G_INT (INT i) {Return G (i);} extern "C" Double g_double (double d) {return g (d);}
here is
C
head File
Wrapper
Example of functions:
INT g_int (int); double g_double (double);
You also need the wrapper function to call the template functions because Template functions cannot be declared as Extern "C": Template
C code can still access the overload function and the Template functions. The C code must use Wrapper Functions.
Access C Class in C
Can I access C Class from C code? Can you declare a C Struct, look like a C Class and can call a member function in some way? The answer is affirmative, although you must increase some complexity to maintain the portability. Any modification of the definition of C Class requires you to re-examine your C code.
Assume that you have a C Class as follows:
Class M {public: Virtual Int foo (int); // ... private: INT I, J;}
You can't declare Class M in C code. The best thing you can do is to pass pointers that point to the Class M object, which is similar to passing the File object in C standard I / O. You can write the Extern "C" function in C to access the Class M object and call these functions in the C code. Below is a C function, designed to call member functions foo:
Extern "C" INT CALL_M_FOO (M * M, INT I) {RETURN M-> Foo (i);}
Below is an example of C code, it uses Class M:
Struct m; / * You can support omly an incomplete declaration * / int call_m_foo (struct m *, int); / * Declare the wrapper function * / int F (struct m * p, int J) / * Now you can Call M :: foo * / {Return Call_m_foo (p, j);}
mixing
Iostream
with
C
standard
I / O
You can
C
Used in the program from the standard
C
head File
of
C
standard
I / O
,because
C
standard
I / O
Yes
C
a part of.
Any mixing in the same program
Iostream
And standard
I / O
The considerations do not depend on whether the program is clearly included.
C
Code. This problem is pure
C
Program use standard
I / O
with
Iostream
it's the same.
Sun C and C use the same C operation time library, which is indicated in the compatible compiler section. With the Sun compiler, you can freely use standard I / O in C and C code in the same program.
C
Standard, you can "stream" in the same goal
Stream
) "Mixing standards
I / O
Function and
Iostream
Functions, such as standard input and output flow. but
C
Implementation may be different on their compliance. Some systems require you to do anything
I / O
Call before
SYNC_WITH_STDIO ()
function. Mixed in the same stream or file
I / O
Style, realistic in I / O
Different effects. Worst, you get the result of making a system call for each character's input. If the program has a lot of
I / O
And performance may be unacceptable.
The safest way is to any given documents
/
Standard flow, adherence to the standard
I / O
or
Iostream
style. Use standards on a file or flow
I / O
, Use in another different file or stream
Iostream
Will not cause any problems.
Pointer with pointing functions
Pointer to point to functions must indicate whether to point to one
C
Function or
C
Function, because
C
with
C
Functions may adopt different calls. Otherwise, the compiler does not know which function call is generated. Most system pairs
C
with
C
There is no different call agreement, but
C
This possibility is allowed. So you must be careful when declaring a pointer to the function, make sure the type matches. Consider the following example:
TYPEDEF INT (INT); // Line 1 Extern "C" void foo (pfun); // line 2 Extern "C" INT G (int) // line 3 ... foo (g); / / Error! // Line 5
LINE 1 declares that PFUN points to a C function because it lacks link specifiers. Line 2 declares that FOO is a C function, which has a pointer to the C function. LINE 5 is trying to call the Foo, G is a C function with a pointer to g, so the type does not match.
To ensure that the link specification for the pointer to the function matches the function you want to point to. In this correct example, all statements are included in the extern "C" curly brackets to ensure type matching.
EXTERN "C" {typedef int (* pfun) (int); void foo (pfun); int G (int);} foo (g); // now OK
Pointing a function pointer has another subtle, it may bring a trap to the programmer. Link specification is applied to all parameter types and return types. If you put a detailed declaration pointing function (
Pointer-to-function
) Used as function parameters, the link specification also acts on the pointer of this pointing function. If you use it
Typedef
Declare a pointer to the function, this
Typedef
Types When used in a function declaration, link specifications will not be affected. For example, consider the following code:
TYPEDEF INT (INT); EXTERN "C" void foo (PFN P) {...} // definition extern "c" void foo (int (*)); // Declaration
The front two lines can appear in a program file, the third line can appear in a header file, in this header file, you don't want to expose internal use.
Typedef
name. Although you want to let
foo
Declarations and definitions match, but they do not match.
foo
Definition accepts a pointing
C
The function of the function, but its statement accepts a pointing
C
The pointer of the function. This code declares a pair of overload functions. (Translation: This is the link specification for parameter types.)
In order to avoid this problem, it is consistently used in the statement.
TypeDefs
Or surrounded by a proper link specification
TypeDefs
. For example, assume you want to let
foo
Accept a pointing C
The pointer of the function, you can write it in the following way
foo
Definition:
Extern "C" {typedef int (* pfn) (int); void foo (PFN P) {...}}
use
C
abnormal
spread(
PROPAGATING
)abnormal
From
C
Call in the function
C
Function, and
C
What will happen? Whether it will make this anomalies have an appropriate behavior
C
Standards are somewhat vague, and you have to take special precautions on some systems. In general, you must ask the user manual to determine if the code works in an appropriate manner.
Preventive measures are not required in Sun C . The abnormal mechanism in Sun C does not affect the way functions call. When the C exception is thrown, if a C function is in an active state, the C function will be transferred to an exception handling process.
Mixing exception and set_jmp, long_jmp best recommendation not to use long_jmp in programs that contain C code. C abnormal mechanisms and C rules that destroy the scope objects may be violated by long_jmp, thereby obtaining uncertain results. Some compilers integrate exceptions and long_jmp, allowing them to work together, but you can't rely on such behavior. Sun C uses the same SET_JMP and long_jmp as the C compiler.
a lot of
C
Experts believe
Long_jmp
It should not be integrated with abnormal, because it is difficult to specify how it should be used.
If you use long_jmp in a C-code C code with C , make sure that long_jmp does not cross the C functions of the cross over. If you can't make sure this, check if you can compile the C code by disabling an exception. If the sectors of the object are bypass, you still have problems.
Link program
At a certain time, most C compilers require the main function to be compiled by C . This requirement is not common today, Sun C does not require this. If your C compiler needs to compile the main function, you can't do this for some reason, you can change the name of the C main function and call it from a C main package function. For example, changing the name of the C main function is c_main, and writes the following C code:
Extern "C" int C_main (int, char **); // Not needed for Sun C int main (int Argc, char ** argv) {return c_main (argc, argv);}
Of course, c_main must be declared in the C code and return an int. If you annotate, use Sun C will not have this trouble.
Even if your program is mainly
C
Composition, but use
C
Library, you need link
C
Running to support
C
The library provided by the compiler is compiled together. The easiest and best way to do this is to use
C
The compiler drives the link process.
C
The compiler's drive knows what library to link, how is the order. Specific libraries can depend on compilation
C
Use options when code.
Assume that you have a C program file main.o, f1.o, and f2.o, you can use the C subscription Helper.a. With Sun C , you have to trigger the command line as follows: cc -o myprog main.o f1.o f2.o helper.a
necessary
C
Running time library, such as
Libcrun
with
LibCStd
Automatically linked.
Helper.a
You may require additional link options. If you cannot use for some reason
C
Compiler, you can use
CC
Command
Dryrun
Options to get the list of commands that have been caused by the compiler and capture them into one
shell
script. Because of the exact order
(
plural
)
Depending on the command line option, you should review -
Dryrun
Option output and any change in the command line.
More information
-
Sun ONE Studio C / C Documentation Sun One C and C compiler, including the MAN man page and readme file.
About author
STEVE CLAMAGE from SUN in 1994? It is currently the technical leadership of the C compiler and the Sun One Studio compiler kit. It began in 1995 to the Chairman of the ANSI C Committee.