In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
The compiling mode and calling convention of the function "C" and the use of extern "C" are introduced in detail in this article. It is hoped that this article can help more partners who want to solve this problem to find a more simple and feasible method.
The compilation and calling conventions of functions and the use of extern "C"
The main difference between C++ compilation and C compilation is that because C++ introduces function overloading (overload), the compiler renames the function with the same name (name mangle). Therefore, citation in C++
When using other C function libraries, the function used by the declaration needs to be handled appropriately to tell the compiler to make appropriate name processing.
The calling convention of the function involves the stack order of the function parameters and the stack cleaning body (the body responsible for cleaning the stack: the function itself or the caller of the function? ), partial name reorganization.
For example, in C compilation mode, there are _ stdcall, _ cdecl and other calling conventions, and in C++ compilation mode, there are also _ stdcall, _ cedecl and other calling conventions.
Two examples of complex modifications:
Extern "C" _ declspec (dllexport) int _ _ cdecl Add (int a, int b); / / C compiler export _ cdecl calls convention functions
Typedef int (_ _ cdecl*FunPointer) (int a, int b)
1. Compilation mode
C compile-time function name decorates the convention rules:
The _ _ stdcall calling convention prefixes the output function name with an underscore prefix, followed by an "@" symbol and the number of bytes of its parameters in the format _ functionname@number.
The _ _ cdecl calling convention only prefixes the output function name with an underscore in the format _ functionname.
The _ _ fastcall calling convention adds an "@" symbol before the name of the output function, followed by a "@" symbol and the number of bytes of its parameters, in the format @ functionname@number.
None of them changes the case of the characters in the output function name, which is different from the pascal calling convention, which outputs the function name without any modification and all capitalization.
C++ compile-time function name modification convention rules:
_ _ stdcall calling convention:
1. With "?" Identifies the beginning of the function name, followed by the function name
2. The function name is followed by "@ @ yg" to identify the beginning of the parameter table, followed by the parameter table
3. The parameter table is represented by a code:
X--void
D--char
E--unsigned char
F--short
H--int
I--unsigned int
J--long
K--unsigned long
M--float
N--double
_ n--bool
....
Pa-- represents a pointer, followed by a code that indicates the pointer type. if pointers of the same type appear continuously, replace them with "0", and a "0" represents a repeat.
4. The first item of the parameter table is the return value type of the function, followed by the data type of the parameter, and the pointer is identified before the data type it refers to.
5. The parameter table is followed by "@ z" to mark the end of the entire name, and if the function has no arguments, it ends with the "z" flag.
Its format is "? functionname@@yg*@z" or "? functionname@@yg*xz", for example
Int test1- "? test1@@yghpadk@z"
Void test2- "? test2@@ygxxz"
_ _ cdecl calling convention:
The rule is the same as the _ stdcall call above, except that the starting identity of the parameter table has changed from "@ @ yg" above to "@ @ ya".
_ _ fastcall calling convention:
The rule is the same as the _ stdcall call above, except that the starting identity of the parameter table has changed from "@ @ yg" above to "@ @ yi".
two。 Calling convention
Calling convention (Calling Convention) refers to a protocol established in a programming language to implement function calls. This protocol specifies the parameter transmitter in the function of the language.
Formula, whether the parameters are variable, and who will handle the stack. Different languages define different calling conventions.
In C++, in order to allow operator and function overloading, the C++ compiler tends to rewrite the symbolic name of each entry point according to certain rules in order to allow the same name (with different parameters)
Number types or different scopes) have multiple uses without breaking existing C-based linkers. This technique is often referred to as Name Mangling or name revision.
Decorate (Name Decoration). Many C++ compiler manufacturers have chosen their own name modification schemes.
Therefore, in order for modules written in other languages (such as Visual Basic applications, Pascal or Fortran applications, etc.) to call functions of DLL written by CAccord +, you must make
Export the function with the correct calling convention, and do not let the compiler decorate the name of the function to be exported.
Calling conventions are used to: (1) handle the order in which the function parameters are passed on and off the stack (the caller or the callee pops the parameters off the stack), and (3) the compiler identifies the function name.
Problems such as the name modification convention and so on.
1 、 _ _ cdecl
_ _ cdecl is the default calling convention used by CCompact + and MFC programs, and can also be manually specified by adding the _ _ cdecl keyword to the function declaration. When the _ _ cdecl convention is adopted, the function parameters are as follows
Enter the stack from right to left, and the caller pops the parameters off the stack to clean up the stack. Therefore, functions that implement variable arguments can only use this calling convention. Because every one of them uses
The functions agreed upon by _ _ cdecl contain code that cleans up the stack, so the resulting executable file size will be large. _ _ cdecl can be written as _ cdecl.
2 、 _ _ stdcall
The _ _ stdcall calling convention is used to call the Win32 API function. With the _ _ stdcal convention, the function parameters enter the stack in the order from right to left, and the called function cleans up the transfer parameters before returning
The stack of numbers, the number of function parameters is fixed. Because the function body itself knows the number of arguments passed in, the called function can use a ret n instruction to clean up the heap passed parameters directly before returning.
Stack. _ _ stdcall can be written as _ stdcall.
3 、 _ _ fastcall
The _ _ fastcall convention is used in situations where performance requirements are very high. The _ _ fastcall convention places the two parameters of the function starting from the left that are less than 4 bytes (DWORD) in the
ECX and EDX registers, the rest of the parameters are still passed on the stack from right to left, and the called function cleans the stack of the passed parameters before returning. _ _ fastcall can be written as _ fastcall.
The keywords _ _ cdecl, _ _ stdcall and _ _ fastcall can be added directly before the function to be output, or they can be selected in the compiled environment's Setting...- > C _ Code Generation option.
Choose. Their corresponding command line arguments are / Gd, / Gz, and / Gr, respectively. The default state is / Gd, which is _ _ cdecl. When the keyword added in front of the output function is different from the choice in the compilation environment, the
The keyword added before the output function is valid.
Comparison of 3._stdcall and _ cdecl calling convention
Can be found in the "windef.h" header file:
# define CALLBACK _ _ stdcall
# define WINAPI _ _ stdcall
# define WINAPIV _ _ cdecl
# define APIENTRY WINAPI
# define APIPRIVATE _ _ stdcall
# define PASCAL _ _ stdcall
# define cdecl _ cdecl
# ifndef CDECL#define CDECL _ cdecl
# endif
Almost every WINDOWS API function we write is of type _ _ stdcall. Why?
First, let's talk about the difference between the two: WINDOWS's function calls require a stack (STACK, a first-in-and-out storage structure). When a function is called
After completion, the stack needs to be cleared. Here is the crux of the problem. How to clear it? If our function uses _ _ cdecl, then the stack cleanup is done by the caller, using the
In the terminology of COM, it is done by the customer. This brings a thorny problem. Different compilers generate stacks in different ways, so whether the caller can be normal.
To complete the clean-up work? The answer is no. If you use _ _ stdcall, the above problem is solved, and the function solves the cleanup work on its own. So, in cross (development) level
In the call to the station, we all use _ _ stdcall (although it sometimes appears as WINAPI). So why do you need _ cdecl? When we come across a letter like this
Such as fprintf (), its parameters are variable and indefinite, and the caller does not know the length of the parameters in advance, and the cleanup work cannot be carried out normally afterwards, so this
In this case, we can only use _ cdecl.
Note:
1. _ beginthread needs the thread function address of _ _ cdecl, and _ beginthreadex and CreateThread need the thread function address of _ _ stdcall.
2. Generally speaking, the function of WIN32 is _ _ stdcall. And there is the following definition in Windef.h:
# define CALLBACK _ _ stdcall
# define WINAPI _ _ stdcall
3. Examples of modifiers for complex function declarations or pointers:
Extern "C" _ declspec (dllexport) int _ _ cdecl Add (int a, int b)
Typedef int (_ _ cdecl*FunPointer) (int a, int b)
4. The function of extern "C" (reference: http://hi.baidu.com/qinfengxiaoyue/item/8bd89e81d1cbeb5226ebd9b4)
Why do standard header files have a structure similar to the following? # ifndef _ _ INCvxWorksh
# define _ _ INCvxWorksh
# ifdef _ _ cplusplus
Extern "C" {
# endif
/ *. /
# ifdef _ _ cplusplus
}
# endif
# endif / * _ _ INCvxWorksh * /
Obviously, the purpose of the compiled macro "# ifndef _ INCvxWorksh, # define _ INCvxWorksh, # endif" in the header file is to prevent the header file from being referenced repeatedly.
that
# ifdef _ _ cplusplus
Extern "C" {
# endif
# ifdef _ _ cplusplus
}
# endif
What is the function of it?
Answer: the variables and functions modified by extern "C" are compiled and linked according to the C language; that is, to realize the mixed programming of C++ and C.
Understanding the motivation for the establishment of extern "C" in C++, let's analyze the common skills of using extern "C" in detail.
Idiom for extern "C":
(1) when referencing functions and variables in C language in C++, when including C language header files (assuming cExample.h), you need to do the following:
Extern "C"
{
# include "cExample.h"
}
However, in the header file of C language, the external function can only be specified as extern type. The declaration of extern "C" is not supported in C language. It will appear when extern "C" is included in .c file.
Grammatical errors in translation.
The source code of the three files included in the project using C++ to quote the C function example is as follows: / * C language header file: cExample.h * /
# ifndef C_EXAMPLE_H
# define C_EXAMPLE_H
Extern int add (int x pencil int y)
# endif
/ * c language implementation file: cExample.c * /
# include "cExample.h"
Int add (int x, int y)
{
Return x + y
}
/ / C++ implementation file, call add:cppFile.cpp
Extern "C"
{
# include "cExample.h"
}
Int main (int argc, char* argv [])
{
Add (2pr 3)
Return 0
}
If C++ calls a .DLL written in C, add extern "C" {} when including the header file of the .DLL or declaring the interface function.
(2) when referencing functions and variables in C++ language in C, the function declaration in the header file of C++ needs to be prefixed with extern "C", but it cannot be referenced directly in C language.
The header file of a function declaration or variable that has been modified by extern "C" (because the extern "C" keyword is not supported in C compilation), you should refer to the C++ in C
The function in is declared as an extern type.
The source code of the three files included in the project with C reference C++ function example is as follows: / / C++ header file cppExample.h
# ifndef CPP_EXAMPLE_H
# define CPP_EXAMPLE_H
Extern "C" int add (int x, int y)
# endif
/ / C++ implementation file cppExample.cpp
# include "cppExample.h"
Int add (int x, int y)
{
Return x + y
}
/ * C implementation file cFile.c
/ * but this will cause compilation errors: # include "cExample.h" because C compilation does not support the extern "C" keyword * /
Extern int add (int x, int y)
Int main (int argc, char* argv [])
{
Add (2,3)
Return 0
}
5. MFC provides some macros. You can use AFX_EXT_CLASS instead of _ _ declspec (DLLexport) and modify the class name to export the class.
AFX_API_EXPORT to modify the function, AFX_DATA_EXPORT to modify the variable
AFX_CLASS_IMPORT:__declspec (DLLexport)
AFX_API_IMPORT:__declspec (DLLexport)
AFX_DATA_IMPORT:__declspec (DLLexport)
AFX_CLASS_EXPORT:__declspec (DLLexport)
AFX_API_EXPORT:__declspec (DLLexport)
AFX_DATA_EXPORT:__declspec (DLLexport)
AFX_EXT_CLASS:#ifdef _ AFXEXT
AFX_CLASS_EXPORT
# else
AFX_CLASS_IMPORT
6. DLLMain is responsible for initializing (Initialization) and ending (Termination) work, whenever a new process or a new thread of that process accesses DLL, or
Every process or thread that accesses DLL will call DLLMain when it no longer uses DLL or ends. However, use TerminateProcess or
TerminateThread ends a process or thread and does not call DLLMain.
7. A DLL has only one instance in memory
The relationship between the DLL program and the program that calls its output function:
1), the relationship between DLL and processes and threads
The DLL module is mapped to the virtual address space of the process that called it.
The memory used by DLL is allocated from the virtual address space of the calling process and can only be accessed by the thread of that process.
The handle to DLL can be used by the calling process; the handle to the calling process can be used by DLL.
DLL can have its own data segment, but does not have its own stack, using the stack of the calling process, which is the same stack pattern as the application that called it.
2) about shared data segments
The global variables defined by DLL can be accessed by the calling process; DLL can access the global data of the calling process. Each process that uses the same DLL has its own DLL global
Variable instance. If multiple threads access the same variable concurrently, you need to use a synchronization mechanism; for a DLL variable, if you want each thread using DLL to have its own
You should use thread local storage (TLS,Thread Local Strorage).
This is the answer to the question about the compilation mode and calling convention of the function, as well as the use of extern "C". I hope the above content can be of some help to everyone. If you still have a lot of doubts to be solved, you can follow the industry information channel for more related knowledge.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.