For information about calling assembly language routines from C or C++, see Using Assembly Language Functions.
Type-safe linkage is an important feature of DMC++, even if only linking C++ modules. It lets you overload functions (give different functions the same name) because it provides the linker with a unique identifier for each function. The compiler mangles the name you give a function, in combination with the number and type of its arguments, to produce a unique identifier for the linker.
Traditional C linkage mechanisms are unsafe because they give the compiler no viable way to check the types of function arguments across separately compiled program modules. This deficiency can cause serious problems at compile time. For instance, suppose the following function is defined in a header file:
void checkit(unsigned char c);
where c is defined as unsigned char because some of the values it needs to check for are in the range 128 through 255. This header is typically included in the file that defines checkit.
As is also common in C programming, checkit is used in a second file. Rather than include the header file, the programmer (per convention) separately declares the prototype for checkit at the top of the second file. The following prototype is used:
void checkit(char c);
If the program is compiled on a system that uses unsigned chars by default, the above code compiles and executed perfectly. However, if the program is then ported to a compiler where chars are signed by default (like DMC++), the program yields unpredictable results because the call to checkit in the second file treats values over 127 as negative.
Bugs of this type can prove very difficult to find because the compiler processes one file at a time and therefore cannot detect type violations in function prototypes across files. But with type-safe linkage, the compiler generates two different internal (hidden) identifiers for the two prototypes. Since no matching function is provided for the second prototype, the linker flags this external function reference as unresolved.
If you accidentally overload a function (that is, if you declare it twice with different argument types), one of these functions will not have a function definition with matching argument types, and the linker will report an unresolved external reference. This happens even if the re-declarations occur in two separately compiled modules.
C does not support C++ linkage. You can call C functions from C++ code but you cannot call C++ functions from C code. With the C++ compiler, you can use the syntax:
extern "C++" { }
to specify C++ linkage when the declaration of a C++ function is nested inside declarations for some other linkage type. See the section "Type-Safe Linkage" in this chapter for more information.
Note: The __near and __far keywords are ignored for member functions and always use the default for the memory model used. This behavior simplifies the implementation of virtual functions.
C linkage is the default linkage for .c files when compiled without the -cpp flag. If a function is declared as using C linkage, and a function definition is found in the C++ source file, that function is compiled as a C function and not as a C++ function. Any calls to that function from other C++ functions are handled correctly.
Digital Mars's C linkage is compatible with the C linkage used by the Microsoft C compiler.
In C++ code, use this syntax to specify C linkage:
extern "C" { }
In C code, you can specify C linkage explicitly by using the __cdecl type modifier, provided you do not require strict ANSI C compatibility.
Note: The compiler recognizes the main function as special and always compiles it with C linkage.
If you wish to retain C linkage for functions that call assembly language routines, remember to ensure that the interface to C++ is correct (see Using Assembly Language Functions for information).
Unless your C modules are compiled with a third-party C compiler, you do not have to recompile them. Follow the steps below to generate an object file and associated header files that you can link to both C and C++ modules. All that is required is a modification of the associated header files.
Note: When constructing makefiles, be sure to run the right compiler for each file. The default extension for C files is .c. Valid extensions for C++ files are .cpp, .cxx, or .cc.
To modify an existing C library to work with Digital Mars C++, insert the following code at the beginning of each header file:
#ifdef __cplusplus extern "C" { #endif
And, at then end of the file, insert this code:
#ifdef __cplusplus } #endif
You can then use the header with both C and C++ files.
Where it is undesirable to modify the header file, you can use the following technique to encapsulate the #include statement in the source file:
extern "C" { #include "c_header.h" }
Once you have modified a header file, you should be able to use the library without difficulty, provided you always include the required headers for the functions you use (as you must for the standard C libraries supplied with the compiler).
The general layout for the DMC++ name mangling is described in the Microsoft Object Mapping Specification, published by Microsoft's Language Business Unit.
The basis for this name mangling is the function name itself, with an added signature that holds information about the class (if any) to which the function belongs and the number and types of its arguments.
When constructing a C++ function name, the compiler takes the original function name as the root of the encoded name. If the function being encoded is a C++ operator, the compiler must also supply a function name to represent the operator.
To view the mangled names of your functions, compile them and then use the dumpobj or obj2asm utilities to view the resulting object file, or link the code and run the unmangle utility on the executable or map file.
You can also examine mangled names in a compiled program with the Digital Mars C debugger or with the Digital Mars C++ debugger in pure C mode.
In DMC++, the FORTRAN and Pascal linkage types behave identically. However, you should use the appropriate specifier for functions of each type because the calling conventions for FORTRAN and Pascal may differ in future releases or on other platforms.
In C++ code, use this syntax to specify Pascal or FORTRAN linkage:
extern "Pascal" { }
or
extern "FORTRAN" { }
You cannot use the C++ syntax in C programs.
Warning: Although the FORTRAN and Pascal linkage methods allow C++ programs to call functions of these types or vice versa, they do not handle any other required conversions. For example, conversions of NULL- terminated C++ strings into Pascal strings with a length prefix are not automatic.
In Digital Mars C++, it is possible to call functions that do not use the default function calling conventions. For instance, system functions in the Microsoft Windows API use Pascal calling conventions. The keywords __cdecl, __fortran, and __pascal tell the C compiler that the functions to which they refer use the calling and parameter-passing conventions of C, FORTRAN, or Pascal, respectively, rather than the default conventions. In this respect, they work in the same way as extern "C", extern "FORTRAN", and extern "Pascal" do in the C++ compiler, except that the extern format also engages the function-naming conventions of the indicated language.
Note: Although you can use these keywords in both C and C++, use them with caution. The preferred method to use with C++ is the extern "C", extern "FORTRAN" or extern "Pascal" syntax. This will make the C++ code portable to other C++ compilers.
For example, to declare Pascal-calling conventions in C:
extern int __pascal my_function();
in C++:
extern "Pascal" int my_function();
Declaring data as __cdecl, __fortran, or __pascal influences how the name appears to the linker. However, the name always appears to the debugger as it appears in the source. __cdecl causes an underscore to be added to the front of the name, which is the default. __fortran or __pascal causes the name to convert to upper case. For example, the following code appears as blang to the linker:
int __pascal blang;
Notice that the keyword appears immediately before the variable name.
Note: If you do not use __cdecl, __fortran, __pascal, or the extern functions, the compiler mangles variable names according to Microsoft specifications. This deviates from the ARM description, which recommends that names not be mangled.
One useful method of ensuring portability to other systems is by conditionally defining the extended keywords as empty:
// Remove extended keywords for non Digital Mars // compilers #if !defined(__DMC__) #define __cdecl #define __pascal #define __fortran #endif
Note: In general, function pointers can cause subtle problems when the function pointed to is not the compiler's default type. The rule to remember is that the extended keyword must appear immediately before the *, which determines that the type is a function pointer. The correct syntax for declaring a pointer to a Pascal function is:
int (__pascal *fp)(void);
AltStyle によって変換されたページ (->オリジナル) / アドレス: モード: デフォルト 音声ブラウザ ルビ付き 配色反転 文字拡大 モバイル