콘텐츠로 이동

C++ 이름 맹글링과 extern "C"

C++ 컴파일러는 함수 오버로딩과 네임스페이스를 지원하기 위해 함수명에 타입 정보를 추가해 고유한 심볼 이름을 생성합니다. 이를 **이름 맹글링(name mangling)**이라 합니다. C 라이브러리 연동이나 동적 라이브러리 개발 시 반드시 이해해야 합니다.


// 소스 코드
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&)

Terminal window
# 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 "

// 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;
}

// mylib.h — C와 C++ 모두에서 사용 가능
#ifdef __cplusplus
extern "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
}
#endif

C++에서는 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);

#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);
}

컴파일러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 파일 크기와 로딩 시간을 줄이세요.