programing

외부 "C" 선언은 어떻게 작동합니까?

css3 2023. 10. 22. 20:20

외부 "C" 선언은 어떻게 작동합니까?

프로그래밍 언어 과목을 수강하고 있는데, 우리는 그 프로그램에 대해 이야기하고 있습니다.extern "C"선언.

이 선언은 "C와 C++를 연결한다"는 것 외에 어떻게 더 깊은 수준에서 작동합니까?이것이 프로그램에서 발생하는 바인딩에도 어떤 영향을 미칩니까?

extern "C"는 다음 기호가 망가지지 않도록 하기 위해 사용됩니다(decorated).


예:

예를 들어, 우리가 다음 코드를 가지고 있다고 가정해 보겠습니다.test.cpp:

extern "C" {
  int foo() {
    return 1;
  }
}

int bar() {
  return 1;
}

.gcc -c test.cpp -o test.o

기호 이름을 살펴봅니다.

00000010T_Z3barv

00000000 Tfoo

foo()이름을 유지하고 있습니다.

C와 C++ 둘 다에서 컴파일할 수 있는 일반적인 함수에 대해 알아보겠습니다.

int Add (int a, int b)
{
    return a+b;
}

이제 C에서 그 함수는 내부적으로 "_Add"라고 불립니다.반면에 C++ 기능은 내부적으로 name-mangling이라고 불리는 시스템을 사용하여 완전히 다른 것이라고 불립니다.이것은 기본적으로 다른 매개 변수를 가진 같은 함수가 다른 내부 이름을 갖도록 함수의 이름을 짓는 방법입니다.

따라서 Add()가 add.c에 정의되어 있고 프로토타입이 add.h에 있으면 c++ 파일에 add.h를 포함하려고 하면 문제가 발생합니다.C++ 코드가 add.c와 다른 이름의 함수를 찾고 있기 때문에 링커 오류가 발생합니다.이 문제를 해결하려면 다음 방법으로 add.c를 포함해야 합니다.

extern "C"
{
#include "add.h"
}

이제 C++ 코드는 C++ name mangled 버전 대신 _Add로 연결됩니다.

그것이 그 표현의 쓰임새 중 하나입니다.결론적으로, 만약 당신이 C++ 프로그램에서 엄밀하게 C인 코드를 컴파일할 필요가 있다면, 당신은 그것을 외부의 "C" {...} 포고문

코드 블록에 외부 "C"로 플래그를 지정하면 시스템에 C 스타일 링크를 사용하도록 지시하는 것입니다.

이것은 주로 링커가 이름을 망치는 방식에 영향을 미칩니다.C++ 스타일 이름 망글링(연산자 오버로드를 지원하는 것이 더 복잡함)을 사용하는 대신, 링커에서 표준 C 스타일 이름을 얻을 수 있습니다.

주의해야 할 점은extern "C"또한 함수의 유형도 수정합니다.더 낮은 수준의 것만 수정하는 것은 아닙니다.

extern "C" typedef void (*function_ptr_t)();

void foo();

int main() { function_ptr_t fptr = &foo; } // error!

의 입니다.&foo일부 컴파일러는 코드를 허용하지 않지만 모든 컴파일러는 허용하지 않습니다.

extern C affects name mangling by the C++ compiler. Its a way of getting the C++ compiler to not mangle names, or rather to mangle them in the same way that a C compiler would. This is the way it interfaces C and C++.

As an example:

extern "C" void foo(int i);

will allow the function to be implemented in a C module, but allow it to be called from a C++ module.

문제는 C 모듈이 C++ 모듈에 정의된 C++ 함수(C++ 클래스를 사용할 수 없음)를 호출하도록 할 때 발생합니다.C 컴파일러는 마음에 들지 않습니다.extern "C".

So you need to use this:

#ifdef __cplusplus
extern "C" {
#endif

void foo(int i);

#ifdef __cplusplus
}
#endif

Now when this appears in a header file, both the C and C++ compilers will be happy with the declaration and it could now be defined in either a C or C++ module, and can be called by both C and C++ code.

In C++ the name/symbol of the functions are actually renamed to something else such that different classes/namespaces can have functions of same signatures. In C, the functions are all globally defined and no such customized renaming process is needed.

To make C++ and C talk with each other, "extern C" instructs the compiler not to use the C convention.

extern "C" denotes that the enclosed code uses C-style linking and name mangling. C++ uses a more complex name mangling format. Here's an example:

http://en.wikipedia.org/wiki/Name_mangling

int example(int alpha, char beta);

C:_example

C++에서:__Z7exampleic

Update: As GManNickG notes in the comments, the pattern of name mangling is compiler dependent.

extern "C", is a keyword to declare a function with C bindings, because C compiler and C++ compiler will translate source into different form in object file:

For example, a code snippet is as follows:

int _cdecl func1(void) {return 0}
int _stdcall func2(int) {return 0}
int _fastcall func3(void) {return 1}

32-bit C compilers will translate the code in the form as follows:

_func1
_func2@4
@func3@4

in the cdecl, func1 will translate as '_name'

in the stdcall, func2 will translate as '_name@X'

in the fastcall, func2 will translate as '@name@X'

'X' means the how many bytes of the parameters in parameter list.

64-bit convention on Windows has no leading underscore

In C++, classes, templates, namespaces and operator overloading are introduced, since it is not allowed two functions with the same name, C++ compiler provide the type information in the symbol name,

예를 들어 코드 스니펫은 다음과 같습니다.

int func(void) {return 1;}
int func(int) {return 0;}
int func_call(void) {int m=func(), n=func(0);}

C++ 컴파일러는 다음과 같이 코드를 번역합니다.

int func_v(void) {return 1;}
int func_i(int) {return 0;}
int func_call(void) {int m=_func_v(), n=_func_i(0);}

'_v' 및 '_i'는 'void' 및 'int'의 유형 정보입니다.

여기 msdn에서 인용한 내용이 있습니다.

"external 키워드는 변수나 함수를 선언하고 외부 링크(이름은 정의된 것이 아닌 파일에서 볼 수 있음)를 지정합니다.변수를 수정할 때 외부는 변수가 정적 지속 시간(프로그램이 시작될 때 할당되고 프로그램이 종료될 때 할당 해제됨)을 갖도록 지정합니다.변수 또는 함수는 다른 소스 파일에 정의되거나 나중에 동일한 파일에 정의될 수 있습니다.파일 범위의 변수 및 함수 선언은 기본적으로 외부에 있습니다."

http://msdn.microsoft.com/en-us/library/0603949d%28VS.80%29.aspx

언급URL : https://stackoverflow.com/questions/2403391/how-does-an-extern-c-declaration-work