본문 바로가기

Study_C, C++

extern "C" 의 의미와 사용이유

728x90
반응형

- extern "C"의 의미

#ifdef __cplusplus
extern "C" {
#endif

..... .....
..... .....

#ifdef __cplusplus
}
#endif
  • extern C : C++에서만 사용되는 Identifier로, 중괄호 안에 정의된 function 또는 header file에 관해서는 mangling하지 말라는 뜻
  • 즉 C언어의 호출 규칙을 사용하도록 함
    • 보통 C에서 선언한 Function이나 Global Variable을 C++에서 사용할 때 선언 
    • extern은 Link의 규칙을 정하는 keyword

 

- Name Mangling

  • C++에서 사용되는 개념으로, C++ compiler 단계에서 이미 선언된 function 혹은 variable의 이름에 function의 arguments와 관련된 일정한 규칙을 가지고 변형하는 것
    • 이름을 크게 바꾸어 mangilng이라는 단어를 사용함
    • Mangling : 어떤 대상을 꼬거나 여러 조각으로 찢어 원래 형태와 달라지게 하는 것
    • Ex) func_example -> _Z10func_examplei
  • 이를 통해 C++에서는 똑같은 이름의 function을 parameter에 따라 구분지을 수 있다
    • 이러한 C++의 기능을 Function Overloading이라 한다

 

- Compiler, Linker

  • Compiler : 고급 언어를 기계어로 번역하여 Object File을 생성
    • 각각의 Source Code에 별도로 동작하여 별개의 Object File을 생성
  • Linker : Symbol을 해석하고 주소를 할당하여 Object File을 Executable File / Library 와 결합
    • 즉 Compile 이후, 생성된 여러 Object File들을 하나의 File로 합침
    • 그 과정에서 함수의 호출 부분과 정의 부분을 연결(Link)
  • extern "C"는 이 'Link' 과정에서 Name Mangling으로 인해 발생하는 문제를 해결하고자 사용됨

 

- extern "C" 사용 이유

  • C++과 달리 C언어에서는 Function Overloading을 지원하지 않으므로, linker가 function을 이름으로만 구분한다
  • 그런데 C언어로 작성된 source code를 include 할 경우, C언어는 다형성을 지원하지 않으므로 mangling된 function의 원형을 알 수가 없어 Link 과정에서 Error가 발생한다

 

  • 예를 들어, 아래와 같이 C언어로 정의된 함수를 포함한 Header Filer을 C++에서 include 할 경우,
// example.h (C)
#ifndef EXAMPLE_H
#define EXAMPLE_H

void c_function(int x);	// Declaration of c_function

#endif // EXAMPLE_H
// example.c
#include "example.h" 

void c_function(int x) {
    /* 
    	Definition of c_function
    */
}
// main.cpp
#include "example.h" 

int main() {
	c_function(10);  // g++ compiler compiles it to the mangled name of c_function
	return 0;
}

 

- C source code : 함수의 정의 부분

gcc -c example.c -o example.o
  • C compiler(gcc)가 c_function의 정의 부분을 포함한 example.c를 compile
  • Name Mangling이 되지 않은 'c_function'의 이름을 포함한 object file 'example.o'을 생성

 

- C++ source code : 함수의 호출 부분

g++ -c main.cpp -o main.o
  • C++ compiler(g++)가 main.cpp를 compile
  • Name Mangling을 통해 'c_function'의 호출 부분을 '_Z10func_examplei'와 같은 이름으로 변형한 object file 'main.o' 생성

 

- Linking : 위 둘을 결합

g++ main.o example.o -o my_program
  • Linker가 'main.o'와 'example.o'를 결합
  • Linker가 'main.o' 내의 'c_function' 호출 부분을 'example.o' 내의 'c_function'의 정의 부분과 대응시키려 함
    • 구체적으로는 Client C Linker가 함수의 이름 ' c_function'를 통해 main.o로 link를 하려 함
  • 이 때, 각 object file 내의 함수의 이름은 아래와 같이 서로 다르므로 linker가 둘을 대응시킬 수 없음
    • 'main.o' 의 함수 호출 부분 :  '_Z10c_functioni'
    • example.o의 함수 정의 부분 : 'c_function'

 

- extern "C" 사용

// main.cpp
extern "C" {
    #include "example.h"
}

int main() {
    c_function(10);
    return 0;
}
  • 이를 해결하기 위해 extern "C"를 사용하여 C++에서의 function의 이름이 C의 linkage를 갖게 한다
    • 즉 Name Mangling을 하지 않도록 하여 client C 코드가 C와 호환되는, 함수의 선언만을 갖고 있는 Header File 사용을 통해 C++의 function에 link할 수 있도록 한다
    • 구체적으로는 Linkage에 사용되는 Function의 이름에 parameter 정보를 추가하지 않는다

 

* C++ 파일에서 C header file (ex) stdio.h)를 사용할 수 있는 이유도 header file에 extern C 처리가 되어있어 C++ source file에서도 mangilng 작업이 진행되지 않게 했기 때문

 

- # ifdef __cplusplus 사용 이유

  • # ifdef _cplusplus : extern "C"는 C++에서만 정의되는 Identifier이므로, C에서 사용할 시 Error가 발생한다
  • 이를 방지하기 위해 코드의 Complier를 위 구문으로 확인한 후 C++일때만 extern "C"를 사용하게 한다
    • 즉 C++ 코드에서 C Headrer file을 사용할 수 있게 한다 
    • __cplusplus는 해당 코드의 Compiler가 C++용임을 의미
// main.cpp
# ifdef __cplusplus
extern "C" {
# endif 

    #include "example.h"

# ifdef __cplusplus
}
# endif

int main() {
    c_function(10);
    return 0;
}

 

  •  g++ --std=c++14 의 경우 _cpluscplus가 201402L

C++ 표준에 따른 _cplusplus 값

  • C++ 표준에 따라 default 값이 달라진다

 

- 정리

  • C Header file을 C++ 코드에서 사용할 경우, C Compiler를 통해 생성된 Object File과 C++ Compiler를 통해 생성된 Object File을 Linker를 통해 결합하게 된다
    • C compiler의 경우 compile 시, Object File에  c_fuction 함수의 이름 자체로의 Symbol을 생성한다
    • 그런데, C++ Compiler의 경우 Object File에 c_function 함수의 이름을 ' _Z10c_functioni' 와 같은 이름으로 mangling한 Symbol을 생성한다
  • 이로 인해, Compile이후 실제로 호출된 함수를 연결하는 Link 과정에서 Linker는 C++ Object file 내의  ' _Z10c_functioni'라는 symbol로 C Object File 내에서 함수의 정의 부분을 찾는데, C compiler는 이 함수를 이름 그대로 갖고 있으므로, link 오류가 발생하게 된다
    • Linker는 Object file 내의 symbol을 기준으로 함수의 선언과 정의를 연결한다 

 

 

 

 

 

 

 

 

 


참고 자료 :

https://stackoverflow.com/questions/1041866/what-is-the-effect-of-extern-c-in-c

 

What is the effect of extern "C" in C++?

What exactly does putting extern "C" into C++ code do? For example: extern "C" { void foo(); }

stackoverflow.com

 

 

https://5kyc1ad.tistory.com/343

 

[C/C++] extern "C"와 네임 맹글링

최근 개인적으로 리눅스 환경에서 C/C++을 혼합해서 쓸 일이 생겼는데, 그때 extern "C"를 사용하면서 알게 된 점들을 작성해 보려고 합니다. 해당 프로젝트는 'https://github.com/skyclad0x7b7/MiniHook' 요놈

5kyc1ad.tistory.com

 

https://noel-embedded.tistory.com/1078

 

extern "C" 의미

extern "C" 의미는 안에 정의된 함수 혹은 헤더파일에 관해서는 맹글링하지 말라는 의미다. 맹글링은 C++에서 사용되는 용어로, C++ 컴파일러 단계에서 함수 혹은 변수이름을 기존과 크게 다르게 바

noel-embedded.tistory.com

 

http://hyacinth.byus.net/moniwiki/wiki.php/C%2B%2B/extern%20%22C%22%20%EB%A5%BC%20%EC%93%B0%EB%8A%94%20%EC%9D%B4%EC%9C%A0

 

C++/extern "C" 를 쓰는 이유

들어가기 앞서, = 네임 맹글링(Name Mangling) = 코드에서 선언한 함수나 변수의 이름을 컴파일러가 컴파일 단계에서 일정한 규칙을 가지고 변형하는 것. 맹글링을 영어 사전에서 찾아보면 난도질 하

hyacinth.byus.net

 

https://noel-embedded.tistory.com/1139

 

__cplusplus 매크로 의미

https://noel-embedded.tistory.com/1078 해당 글에서 extern "C"의 의미를 대략 파악했다. 결국에는 c 소스를 cpp에서 가져다 쓸 때 맹글링 작업을 막는 것이다 stdlib.h 안에 내용인데 ifdef __cplusplus가 정의되어

noel-embedded.tistory.com

 

https://spikez.tistory.com/19

 

C++ 상에서 발생하는 name mangling 에 관한 내용

이 글에서 다뤄보고자 하는 내용은 2가지 입니다. 하나는 name mangling 이고 다른 하나는 extern "C" 입니다. 이 두가지는 c와 c++의 호환성과 관련된 부분이기도 하고 라이브러리를 사용하다보면 가끔

spikez.tistory.com

 

728x90
반응형

'Study_C, C++' 카테고리의 다른 글

Visual Studio에서의 <bits/stdc++.h> 사용법  (1) 2023.08.29