Odnośniki
|
[ Pobierz całość w formacie PDF ] void func(int);, a given compiler can generate the corresponding mangled name __x_func@i@, where the affix x indicates a function, func is the function's user-given name, @ indicates the beginning of the parameter list, i indicates the type of the parameter, and the closing @ sign signals the end of the parameter list. An overloaded version of f() has a different mangled name because it has a different parameter list. The original user-given name can be reproduced from the mangled name, so linkers in general can issue error messages in a human-readable format. As was previously stated, the name mangling scheme of a given compiler can change from one version to another (for example, if the new version supports namespaces, whereas the previous one did not). This is one of the reasons you often have to recompile your code with every compiler upgrade. Another important implication is that, usually, the linker and the compiler need to come from the same vendor and have compatible versions. This ensures that they share the same naming conventions and that they produce compatible binary code. Calling C++ Code from C Code Up until now, you have observed the C++ side of the story. A C program cannot #include the header file decl.hpp because the extern "C" specifier is not recognized by a C compiler. To ensure that the declaration can be parsed by a C compiler, extern "C" needs to be visible to a C++ compiler -- but not to a C compiler. A C++ function with C linkage has to be declared in two distinct forms, one for C++ and another for C. This can be achieved by using separate C and C++ header files. The C header file looks similar to the following: /*** filename decl.h ***/ void f(int n); /* identical to the C++ header but no extern "C" here */ /*** decl.h ***/ The header file can be #included in the C source file that calls the function f(). For example /*** filename do_something.c ***/ #include "decl.h" void do_something() { f(5); } /*** do_something.c ***/ Keeping separate header files for C and C++ is not an elegant solution, however. The header files have to remain in sync all the time, and when many header files are used, this can turn into a serious maintenance problem. A better alternative is to use one or more C header files for the declarations. For example /*** filename f.h ***/ void f(int n); /* identical to the C++ header but no extern "C" here */ /*** f.h ***/ /*** filename g.h ***/ void g(const char * pc, int n); /*** g.h ***/ Next, the C header files are #included in a C++ header file that contains an extern "C" block: // filename decl.hpp extern "C" { #include "f.h" #include "g.h" } // filename decl.hpp The effect of an extern "C" block is as if every declaration in the #included header files had a preceding extern "C" specifier. Another alternative is to modify the C header file directly by adding an #ifdef directive to make the extern "C" declaration visible only to a C++ compiler. For example /*** filename decl.h ***/ #ifdef __cplusplus extern "C" { //visible only to a C++ compiler #endif void g(const char * pc, int n); void f(int n); #ifdef __cplusplus } //visible only to a C++ compiler #endif /*** g.h ***/ This way, only one header file is needed. However, it is not always possible to modify the C header files directly. In such cases, the preceding technique needs to be used. Please note that a C++ function called from C code is an ordinary C++ function. It can instantiate objects, invoke their member functions, or use any other C++ feature. However, some implementations might require special configuration settings to ensure that the linker has access to the C++ libraries and template codes. Compiling main() Functions can be compiled by either a C compiler or a C++ compiler. However, a C++ compiler should compile main(). This enables a C++ compiler to take care of templates, static initialization, and additional implementation-dependent operations for which main() is responsible. Compiling main() under a C compiler will most likely result in link-time errors due to the different semantics of main() in C and C++. Minimize the Interface Between C and C++ Code In general, you can call a C function from C++ code without special adjustments. The opposite, as you have seen, is also possible -- but it requires additional adjustments. It is therefore recommended that you keep the interface between the two languages at a minimum. Declaring every C++ function as extern "C", for example, is not recommended. Not only does this convention imply additional modifications to the header files, it also disables overloading. Remember also that you cannot declare a member function extern "C". For C++ functions that have to be called from C code, it might be advantageous to use a function wrapper that has an extern "C" specifier. In this case, the wrapped C++ functions can have the C++ linkage. For example void g(const char * pc, int n); //extern "C" is unnecessary void f(int n); extern "C" void f_Wrapper(int n) //only the wrapper function is called from C { f(n); } extern "C" void g_Wrapper(const char *pc, int n) { g(pc, n); } Mixing Classes with Functions It is possible to use both classes and library functions in the [ Pobierz całość w formacie PDF ] |
|||
Sitedesign by AltusUmbrae. |