C++ 이름 맹글링과 extern "C"
C++ 컴파일러는 함수 오버로딩과 네임스페이스를 지원하기 위해 함수명에 타입 정보를 추가해 고유한 심볼 이름을 생성합니다. 이를 **이름 맹글링(name mangling)**이라 합니다. C 라이브러리 연동이나 동적 라이브러리 개발 시 반드시 이해해야 합니다.
1. 이름 맹글링 예시
섹션 제목: “1. 이름 맹글링 예시”// 소스 코드namespace Math { int add(int a, int b); double add(double a, double b); void process(const std::string& s);}
// 컴파일 후 심볼 (GCC, Itanium ABI 기준)// _ZN4Math3addEii → Math::add(int, int)// _ZN4Math3addEdd → Math::add(double, double)// _ZN4Math7processERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE// → Math::process(const std::string&)2. 심볼 확인 도구
섹션 제목: “2. 심볼 확인 도구”# nm으로 오브젝트 파일 심볼 확인nm -C libmylib.a # -C: 디맹글링(demangling)
# objdump로 심볼 덤프objdump -t -C myapp.o
# c++filt으로 맹글링된 이름 디맹글링echo "_ZN4Math3addEii" | c++filt# 출력: Math::add(int, int)
# readelf로 동적 심볼 확인readelf -Ws libmylib.so | grep " T "3. extern “C” — C 링키지 선언
섹션 제목: “3. extern “C” — C 링키지 선언”// C++ 함수를 C에서 호출 가능하게extern "C" { int add(int a, int b); // 맹글링 없음 → 심볼: "add" void process(const char* s);}
// 구현extern "C" int add(int a, int b) { return a + b;}4. C/C++ 헤더 공용 패턴
섹션 제목: “4. C/C++ 헤더 공용 패턴”// mylib.h — C와 C++ 모두에서 사용 가능#ifdef __cplusplusextern "C" {#endif
typedef struct MyHandle MyHandle;
MyHandle* mylib_create(void);void mylib_destroy(MyHandle* h);int mylib_process(MyHandle* h, const char* data, int len);
#ifdef __cplusplus}#endifC++에서는 extern "C" 블록이 적용되고, C 컴파일러에서는 무시됩니다.
5. 동적 라이브러리 심볼 가시성
섹션 제목: “5. 동적 라이브러리 심볼 가시성”// GCC/Clang — 심볼 가시성 제어#define EXPORT __attribute__((visibility("default")))#define HIDDEN __attribute__((visibility("hidden")))
EXPORT int public_api(); // .so 외부에서 접근 가능HIDDEN int internal_impl(); // .so 내부에서만 접근
// CMake 설정// target_compile_options(mylib PRIVATE -fvisibility=hidden)// → 기본 hidden, EXPORT만 노출Windows DLL:
#ifdef _WIN32 #ifdef BUILDING_MYLIB #define MYLIB_API __declspec(dllexport) #else #define MYLIB_API __declspec(dllimport) #endif#else #define MYLIB_API __attribute__((visibility("default")))#endif
MYLIB_API int my_function(int x);6. dlopen/dlsym으로 동적 로드
섹션 제목: “6. dlopen/dlsym으로 동적 로드”#include <dlfcn.h>
void load_plugin(const char* path){ void* handle = dlopen(path, RTLD_LAZY); if (!handle) { std::cerr << dlerror() << '\n'; return; }
// extern "C" 함수만 이름으로 로드 가능 using CreateFn = Plugin*(*)(); auto create = reinterpret_cast<CreateFn>(dlsym(handle, "create_plugin"));
if (auto* err = dlerror()) { std::cerr << "심볼 없음: " << err << '\n'; dlclose(handle); return; }
Plugin* plugin = create(); plugin->run();
dlclose(handle);}7. 컴파일러별 ABI 차이
섹션 제목: “7. 컴파일러별 ABI 차이”| 컴파일러 | ABI | 맹글링 규칙 |
|---|---|---|
| GCC/Clang (Linux) | Itanium ABI | _Z 접두사 |
| MSVC (Windows) | Microsoft ABI | ? 접두사 |
| GCC (MinGW) | Itanium ABI | _Z 접두사 |
MSVC와 GCC는 C++ 심볼 호환이 안 되므로 크로스 컴파일러 라이브러리는 extern "C" 인터페이스를 사용해야 합니다.
이름 맹글링은 오버로딩과 네임스페이스를 링커 수준에서 구현하는 메커니즘입니다. C 상호운용이나 동적 라이브러리 공개 API는 extern "C"로 맹글링을 비활성화하고, __attribute__((visibility("hidden")))으로 내부 심볼을 숨겨 .so 파일 크기와 로딩 시간을 줄이세요.