출처 : http://blog.naver.com/dreamakr?Redirect=Log&logNo=80003636883
친구넘한테 전화가 왔다. C에서 C++에서 작성한 라이브러리를 사용하고 싶다네.
C 나 C++ 소스가 컴파일 될때 우리가 선언한 함수들은 우리가 선언한 이름 그대로 남아 있지 않다.
컴파일러가 파라미터나 calling convention에 따라서 이름을 바꾸는데 이렇게 이름을 바꾸는 것을
name mangling 이라고 한다.
예를 들자면 c++같은 경우를 보면 함수 overriding이 가능하다.
즉 같은 이름으로 파라미터만 다르게 선언해서 사용할수 있다는 예기다. 그럼 컴파일러는 이 같은 이름에 놈들을 어떻게 구분하느냐 파라미터에 type을 가지고 그 함수 명을 변경해 버린다.
다른 함수들도 마찬가지다.
MSVC같은경우 .. 음 예전에 자료가 있었는데.. 찾으면 올리고.. 아님 말고..
예를 하나 들자면
void func_a( void ) ; 란 함수를 lib 로 만들어서 보면
"func_a@@YAXXZ"이런 식으로 변경되어 있을것을 볼수 있다.
더 자세히 보자
test.cpp
extern void func_a( void ) ;
extern "C" void func_b( void ) ;
void func_a( void )
{
return ;
}
void func_b( void )
{
return ;
}
두개의 함수를 똑같은 타입으로 선언했다. 차이점은 보는 봐야 같이 한넘은 extern "C" 를 이용했고 다른 한넘은 그렇지 않다는 차이 뿐이다.
그럼 이넘을 컴파일해서 라이브러리로 만들어서 hex로 덤프뜨면 아래와 같다.
하여튼 이넘때문에 C에서 C++에서 작성한 라이브러리를 사용하고 싶을때는 C++ 라이브러리를 작성할때 애초에 C에서 사용될수 있다는것을 염두해 두고 작성해야 한다는 말이다.
즉 C에서 호출할수 있도록extern "C"를 선언하는 것이다.
역시 코드로 보자
C++ 라이브러리쪽
cpp.h
extern "C" void cpp_create( void ) ;
extern "C" void cpp_destroy( void ) ;
extern "C" void cpp_print(const char *) ;
cpp.c
class dummy {
void print( const char* msg ) {
printf( msg ) ;
}
} ;
static dummy* _theDummy = NULL ;
void cpp_create( void )
{
if( _theDummy == NULL )
{
_theDummy = new dummy ;
}
}
void cpp_destroy( void )
{
if( _theDummy )
{
delete _theDummy ;
}
}
void cpp_print( const char* msg )
{
if( _theDummy )
{
_theDummy->print( msg ) ;
}
}
cpp.h파일에서 보는 봐야 같이 C에서도 사용 되는 넘들은 extern "C"를 선언했다.
반대로
CPP에서 C에서 작성한 라이브러리 사용하려면 어떻게 할까?
여기서도 마찬가지로 모든 함수에 extern "C"를 무조건 선언하는 것이다.
즉 C에서 사용되던 C++에서 사용되던 같은 이름이 사용되도록 extern "C"를 붙여 둠으로써
어디서든 같은 이름으로 링크되는것을 보장해 준다.
먼소린지 모르겠다고? 흠..
즉C에서 작성한 라이브러리는 .h 파일과 .lib파일로 구성되어 있을것이다.
c.h
void c_func(void) ;
c.c
void c_func( void )
{
printf( "여기는 C") ;
}
이 라이브러리를 C언어를 사용하는 프로젝트에서 사용하는경우같은 환경임으로 아무 문제 없이 링크가 수행될테지만 만약C++소스에서 호출되는 경우link에러가 발생하게 된다.
즉어떤 CPP파일
call.cpp
#include "c.h"
void main(void )
{
c_func( ) ;
}
요런경우링크에러다.즉 CPP에서는 C에서와는 다른 name mangling을 수행함으로 c_func라는 함수 이름을 c_func@@XXYYZ 이런식으로 찾을꺼라는 말이다. 그럼 당연이 그런 이름에 함수가 없음으로에러가 발생한다.
즉이렇듯 c++에서도사용 가능하게 하려면 name mangling을 C 형태로 수행하도록 하면 되는것이다.
c.h
extern "C" void c_func( void ) ;
이것처럼 c 에서 작성하는 라이브러리에 함수는 무조건 extern "C" 를 지정하는 것이다.
이상..
방금 C에서 C++로 만든 lib에서 export한 함수를 호출해 봤더니 이런 에러가 나더군
Linking...
caller_namemangling.obj : error LNK2001: unresolved external symbol _func_a
Debug/caller_namemangling.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
즉 c쪽에서는 func_a() 라는 함수를 호출했지만 이넘이 C++쪽에서 만들어진 넘이라
이름이 좀 다르다 앞에서 설명했던것처럼 func_a@@XXYYZ 뭐 이런식에 이름이였을것이다. 따라서 링크할때 찾을수 없어서 에러가 나는것이다.
그 역도 마찬가지
'UNIX_LINUX_C_C++' 카테고리의 다른 글
좋은 정보가 많은 블러그 목록 (0) | 2011.10.16 |
---|---|
Linux 에서 pthread를 최대 생성가능한 thread 수를 측정 (0) | 2011.10.16 |
bind error 방지 하기 (0) | 2011.10.16 |
Poll_thread 소켓 (0) | 2011.10.16 |
extern의 사용 (0) | 2011.10.16 |