반응형
system 내의 binary 호환성을 갖추기 위해서는 가장 먼저 고려해야 할 사항이 바로 ABI를 맞추는 것이다.
 
ABI 란? 
Application Binary Interface 의 약자로, 바이너리(binary), 즉 실행파일이나 라이브러리 간의 저수준(low level)의 인터페이스를 의미합니다.
호출형식이나 데이터 형식이 동일한 모듈들끼리만 모듈내의 함수 호출이나 데이터 사용이 가능해 지는 것이 당연하겠죠?
 
ABI를 결정하는 가장 큰 요소는 Compiler입니다. 
C++ Compiler의 경우, 각 compiler별로 name mangling 규칙이 다른데요.
이때문에 서로다른 compiler에서 만들어진 바이너리간의 호출이 불가능해질 수도 있게 됩니다.
                 name mangling 참조  
 
Compilervoid h(int)void h(int, char)void h(void)
Intel C++ 8.0 for Linux _Z1hi _Z1hic _Z1hv
HP aC++ A.05.55 IA-64
IAR EWARM C++
GCC 3.x and higher
Clang 1.x and higher[3]
GCC 2.9.x h__Fi h__Fic h__Fv
HP aC++ A.03.45 PA-RISC
Microsoft Visual C++ v6-v10 (mangling details) ?h@@YAXH@Z ?h@@YAXHD@Z ?h@@YAXXZ
Digital Mars C++
Borland C++ v3.1 @h$qi @h$qizc @h$qv
OpenVMS C++ v6.5 (ARM mode) H__XI H__XIC H__XV
OpenVMS C++ v6.5 (ANSI mode)   CXX$__7H__FIC26CDH77 CXX$__7H__FV2CB06E8
OpenVMS C++ X7.1 IA-64 CXX$_Z1HI2DSQ26A CXX$_Z1HIC2NP3LI4 CXX$_Z1HV0BCA19V
SunPro CC __1cBh6Fi_v_ __1cBh6Fic_v_ __1cBh6F_v_
Tru64 C++ v6.5 (ARM mode) h__Xi h__Xic h__Xv
Tru64 C++ v6.5 (ANSI mode) __7h__Fi __7h__Fic __7h__Fv
Watcom C++ 10.6 W?h$n(i)v W?h$n(ia)v W?h$n()v
 

 

ABI는 calling convention,  데이타 타입, 사이즈(size),argument , 등등에 대한 내용이 있습니다.

 

인텔의 경우 iBCS라는 인텔에서 정의한 표준을 정의 하고 있습니다.

 

 

 

 
 
EABI 란 ? 

Embedded ABI 

 

 

EABI( 임베디드 애플리케이션 바이너리 인터페이스 )는 임베디드 운영 체제 와 함께 사용하기 위한 파일 형식 , 데이터 유형, 레지스터 사용, 스택 프레임 구성 및 임베디드 소프트웨어 프로그램 의 기능 매개변수 전달에 대한 표준 규칙을 지정합니다 .

EABI를 지원하는 컴파일러는 다른 컴파일러에서 생성된 코드와 호환되는 개체 코드를 생성하므로 개발자는 한 컴파일러로 생성된 라이브러리를 다른 컴파일러로 생성된 개체 코드와 연결할 수 있습니다. 자체 어셈블리 언어 코드를 작성하는 개발자는 호환 컴파일러에서 생성된 어셈블리와 인터페이스할 수도 있습니다.

EABI는 임베디드 시스템의 제한된 리소스 내에서 성능을 최적화하도록 설계되었습니다. 따라서 EABI는 복잡한 운영 체제에서 커널과 사용자 코드 간에 이루어지는 대부분의 추상화를 생략합니다. 예를 들어, 더 작은 실행 파일과 더 빠른 로딩을 허용하기 위해 동적 연결을 피할 수 있으며, 고정된 레지스터 사용을 통해 더 컴팩트한 스택과 커널 호출을 허용하고, 권한 있는 모드에서 응용 프로그램을 실행하면 장치 드라이버를 호출하는 간접적인 작업 없이 사용자 지정 하드웨어 작업에 직접 액세스할 수 있습니다. EABI의 선택은 성능에 영향을 미칠 수 있습니다. 

널리 사용되는 EABI에는 PowerPC , Arm EABI   MIPS EABI 포함됩니다. C 라이브러리와 같은 특정 소프트웨어 구현은 보다 구체적인 ABI 형성하기 위해 추가적인 제한을 부과할 있습니다 가지 예는 ARM GNU OABI EABI이며 ARM EABI 하위 집합입니다.

 
 
Link: en.wikipedia.org
An embedded-application binary interface (EABI) specifies standard conventions for file formats, data types, register usage, stack frame organization, and function parameter passing of an embedded software program.
 
 
 
 
 
 
반응형

요즘 고민하고 공감하는 글이라 스크랩 해왔습니다.


호환성 (Compatibility) 이라는 말을 들어보셨나요?
  • .NET 3.0 버젼 Framework에서 .NET 2.0으로 구현했던 Application이 돌아가지 않는다면?
  • JDK 1.6버젼에서 JDK 1.4 Framework 기반의 Application이 돌아가지 않는다면?

새로 나온 제품이 아무리 좋은 기능이 많이 추가 되어 있더라도..예전 제품과 호환이 되지 않는다면, 그 제품은 잘 팔리지 않을 겁니다. 이번 POST 를 통해 우리가 Product 또는 Framework을 만들때 고려해야 되는 호환성과 여러가지 종류에 대해서 공유하고자 합니다.



Cross-Version Compatibility

 동일한 제품의 다른 버젼에서 만들어진 코드가 호환성을 가지는 지를 언급하는 말로, 예를 든다면 Microsoft SQL 2000에 사용했던 SQL 스크립트가 2005에서도 잘 돌아가는 예를 말하는 것입니다

Backward Compatibilty 와 Forward Compatbility 

하위 호환성 - 하위 제품의 소스,포멧등이 최신 제품과 호환 될때이며, 상위 호환성 - 상위 제품의 소스, 포멧등이 하위 제품과 호환될때를 말합니다.

 

많은 제품들이 하위 호환성은 잘 지원합니다. 예를 든다면 Microsoft Office 2007에서 Microsoft Office 2003이 만든 포멧들과는 잘 호환이 된다고 볼수 있습니다.

하지만 골치 아픈 문제는 상위 호환성인데, Microsoft Office 2007에서 만든 Word , PowerPoint 파일들이 2003에서도 사용할수 있을까요?

아시다시피 두 제품은 완전히 다른 파일 포멧을 가지고 있어서, 2003을 위한 별도의 변환 툴을 제공하여 상위 호환성을 제공할려고 합니다.

단순히 읽기만 되지 편집이 되지 않기 때문에, 완벽한 상위 호환성을 갖추었다고 볼수는 없습니다.

하지만 이 이면에는 또 설계자들이 고려해야 하는 골치 아픈 문제들이 숨겨져 있습니다.

Cross-Redist Compatibiltiy

 서로 다른 제품에서 만들어진 코드가 잘 호환이 되는지.

예) Oracle에서 사용한 Query가 Microsoft SQL에서도 잘 호환이 되는지?

Turbo C에서 동작하던 코드가 Visual C++ 에서도 잘 동작하는지?

Binary Compatibilty

 예전버젼에서 만들어진 바이너리 파일이 새 버젼에서도 재 컴파일 없이 잘 호환이 되는지.

Source Compatibilty

 서로 다른 버젼이지만 변경없이 소스코드 컴파일이 잘 되는지

API Compatibility

 서로 다른 버젼의 API간에 호환성을 제공하는 말로,호환성의 레벨이 Source Compatiblity보단 더 크고, Binary Compatibility 보다는 약한 경우인데요.

Source Compatbility는 입력 파라메터나 리턴값에 공변형 (Covariant) Type을 사용할수 있지만, API는 그러지 못합니다.


 호환성을 버리는 경우..

  • 정책적으로 호환성을 버리는 경우도 있습니다.

혹시 이런말은 들어보신적 있나요? .NET의 적은 JAVA가 아니라. 예전 .NET 이다.

이말의 의미는 .NET  2.0에서도 동작하는 코드가 .NET 3.0 코에서도 잘 동작하기 때문에, 굳이 개발자가 .NET 3.0을 사용하지 않는 다는 말입니다.

.NET 3.0 에 아주 좋은 기능을 넣어 놓아도, 굳이 예전 함수들을 이용해도 잘 돌아가는데 굳이 새로운 기능을 이용할 필요가 있냐? 라는 애기이지요.

물론 JDK 에서도 동일한 문제가 발생합니다.

이것은 새로운 기능을 넣은 Framework 설계자들에게는 상당히 골치 아픈 문제입니다. 훨씬 뛰어난 기능을 추가했음에도 불구하고 하위호환성으로 인해 예전 기능을 그대로 사용하기 때문이지요. 이럴땐 최악의 경우 어쩔수 없이 예전 기능을 포기하기도 합니다.

 

  • 전혀 새로운 패러다임의 등장으로 인해 내부를 다 뜯어 고쳐야 하는 경우를 위해.

이 경우는 아마 VS 6.0과 .NET의 관계이지 않을까 쉽습니다.

Web과 Web Service 라는 새로운 패러다임의 득세로 인해 과감히 VS 6.0 스타일을 버리고 새로운 .NET 을 내놓은 경우입니다.

 

또 PS3와 같이 가격적인 문제로 PS2와 호환이 안되는 제품을 출시한 예와 같이 다양한 이유가 존재할수도 있습니다. 혹시 어쩔수 없이 호환성을 포기할 수 밖에 없었던 다른 이유가 있으신 분은 같이 공유해 주시길 바랍니다.

그 이외에도 호환성에 대한 다양한 이야기가 있으면 Posting 해주시고 트랙백을 부탁드립니다.



Link: http://blog.it-hero.co.kr/blog_post_156.aspx

2008-12-18 14:16:43



반응형

 

이 글에서 다뤄보고자 하는 내용은 2가지 입니다.

하나는 name mangling 이고 다른 하나는 extern "C" 입니다.

이 두가지는 c와 c++의 호환성과 관련된 부분이기도 하고 라이브러리를 사용하다보면 가끔 문제를 일으키는 부분이기도 한 부분입니다.

1. name mangling 이란?


간단히 말하면 compiler 가 임의로 함수나 변수의 이름을 변경하는 것을 의미합니다.
그렇다면 왜 함수나 변수의 이름을 변경하는 것인가?
이를 설명하기 위해서는  C++언어의 성격상 function overloading을 먼저 설명해야 하는데요.

함수 오버로딩(function overloading)이란 개발자가 소스코드를 작성할때 같은 이름으로 다른 기능들을 수행하는 함수를 만들수 있도록 하는 기능을 예기합니다.

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

 


위와 같이 Add라는 함수를 int형을 더하는 함수, float 형을 더하는 함수, 세개의 변수를 더하는 함수등등 여러개의 함수를 작성하고, 개발자가 이를 용도에 맞게 쓸수 있습니다.

이런것이 가능하도록 해주는 기능이 바로 함수 오버로딩이라는 개념입니다.

그럼 컴파일러(compiler)는 소스 코드에서 Add를 호출 했을때 어떻게 각각의 Add를 알아서 찾는가 하는 의문이 생길수 있을것인데,  이를 가능하게 해주는것이 name mangling 입니다.

compiler는 symbol을 생성할때 함수 이름과 함수 parameter를 고려 하여 symbol을 만듭니다.
즉,
int Add( int a,int b)  -> Add + int+ int --> Addii 와 같은 형식으로 만든다는 것입니다.
물론, compiler 마다 다른 mangling 규칙을 가지고 있습니다.

인터넷에 떠도는 문서들을 찾다보니 아주 한눈에 잘 들어오도록 정리된 표가 있어서 샤샥!! 퍼옴...


 

Compiler void h(int) void h(int, char) void h(void)
Intel C++ 8.0 for Linux _Z1hi _Z1hic _Z1hv
HP aC++ A.05.55 IA-64 _Z1hi _Z1hic _Z1hv
GNU GCC 3.x and 4.x _Z1hi _Z1hic _Z1hv
HP aC++ A.03.45 PA-RISC h__Fi h__Fic h__Fv
GNU GCC 2.9x h__Fi h__Fic h__Fv
Microsoft VC++ v6/v7 ?h@@YAXH@Z ?h@@YAXHD@Z ?h@@YAXXZ
Digital Mars C++ ?h@@YAXH@Z ?h@@YAXHD@Z ?h@@YAXXZ
Borland C++ v3.1 @h$qi @h$qizc @h$qv
OpenVMS C++ V6.5 (ARM mode) H__XI H__XIC H__XV
OpenVMS C++ V6.5 (ANSI mode) CXX$__7H__FI0ARG51T CXX$__7H__FIC26CDH77 CXX$__7H__FV2CB06E8
OpenVMS C++ X7.1 IA-64 CXX$_Z1HI2DSQ26A CXX$_Z1HIC2NP3LI4 CXX$_Z1HV0BCA19V
SunPro CC __1cBh6Fi_v_ __1cBh6Fic_v_ __1cBh6F_v_
Tru64 C++ V6.5 (ARM mode) h__Xi h__Xic h__Xv
Tru64 C++ V6.5 (ANSI mode) __7h__Fi __7h__Fic __7h__Fv
Watcom C++ 10.6 W?h$n(i)v W?h$n(ia)v W?h$n()v

 

위와 같이 컴파일러 마다 다른 mangling 규칙을 가지고 있답니다..

 

 

 

자! 그럼 C에 대한 이야기도 해야 하는데요, C의 경우는 mangled 된 함수 이름이 필요 없습니다.
이유는 C에서는 함수 오버로딩(function overloading)을 지원하지 않기 때문에 한 binary안에서는 하나의 함수만 존재 합니다.( 더 정확히는 하나의 symbol 만 허용됩니다.)
하지만 !!!  실제로 컴파일을 해보면 각 함수 이름을 살짝 바꿔 놓기는 합니다.
void Add(int a,int b) ---> _Add 라는 형식 으로 앞에 '_'를 붙입니다.  C++로 작성된 함수의 심벌(symbol) 과는 다릅니다.

C언어의 경우에는 함수 앞에 _를 붙이는 것이 표준인듯 합니다. 이부분에 대해서 찾아본 것이 아니라서 장담은 할 수 없지만 모든 컴파일러들이 공통일 것입니다.)


이런 변경이름(mangled name) 을 확인 해보는 방법은 컴파일된 object file(xxx.o) 나 실행 화일 또는 .lib 파일을 hex editor로 열어서 확인 해보면 눈으로 볼 수 있답니다.


2. extern "C" ?

C/C++ 호환 및 binary 호환 과 같은 주제들을 다루고 고민하다보면, abi니 eabi 니 name mangling 이니 compiler 호환이니 하는 단어들이 나오게 됩니다.

그중에 이 extern "C" 도 가끔 보이구요.  그래서 extern "C" 에 대해서 좀 더 자세히 다뤄보고 저의 경험을 토대로 예기 해보고자 이 글을 쓰게 되었습니다.

저도 언어를 처음 배울때에는 막연하게 "extern "C"를 붙이면 함수의 이름이 C 처럼 나오기 때문에 C++로 짜여진 함수도 C에서 사용할 수 있다." 라고만 알고 있었습니다.

이런 저런 개발을 하다보니 정확한 용법이나 메카니즘을 이해하지 않고 막연하게 사용하는 코드들이나 개념들은 결국 부메랑이 되어 저에게 돌아오더군요.!!
무슨 말이냐 하면,C++에서 짠 함수가 C에서도 사용할수 있게 하려면  extern "C" 를 붙이라는데 어디다? 어떻게 ? 라는 의문이 생겨날 것입니다.
근데 extern "C"에 대해 잘 모르는 사람이 위와 같은 조언을 들었으면,, 분명 extern "C"를 남발하게 됩니다.!!  이는 결국 나중에 compile error를 양산하기도 하고, 코드를 지저분하게 만들기도 하고, 아무튼 문제를 많이 일으키게 되죠.!!! 그런적 없다구요? 전 당했습니다.!! 


자 그럼 하나 하나 차근 차근 짚어 보겠습니다.


extern "C"  --> 이 형식은 extern "C" 이후에 오는 내용을 name mangling 하지 않고 C처럼 symbol을 만들 어라 라는 명령어입니다.

즉, abc.cpp 라는 소스코드에서 아래 abc라는 함수와 def라는 함수를 예로 들어보면,

[file : abc.cpp]

int abc(int a,int b) //abcii 라는 mangled 된 이름을 symbol로 가지게 됩니다.
{
return 0;
}

extern "C" int def(int a,int b)  // def 라는 symbol을 가지게 되는 것입니다.
{
return 0;
}

def는 ii 같은 것이 추가되지 않고 그냥 def라는 이름을 갖게 됩니다.

그러면, 모든 함수 구현 루틴에 extern "C" 를 붙이는것이 사실 귀찮고 힘든 일입니다.
그래서 , 연륜이 있는 개발자들은(저처럼 ㅋㅋㅋ)  extern "C" {}를 활용하게 되는 것이죠.

[file : abc.cpp]

extern "C"
{//<-- extern 시작
int abc(int a,int b) //abcii 라는 mangled 된 이름을 symbol로 가지게 됩니다.
{
return 0;
}

int def(int a,int b)  // def 라는 symbol을 가지게 되는 것입니다.
{
return 0;
}
}//extern 끝

이렇게 extern "C" {}를 사용하면 {} 안에 있는 모든 내용은 name을 mangling하지 않는 다는 선언이 됩니다.

이렇게 사용하면 모든 함수들을 따라다니면서 extern "C" 를 붙일 필요가 없어지는 것입니다.


또, 다른 형식으로 사용하는 case가 Header file extern "C"를 사용하는 경우가 있습니다.
(대단히 많이 사용하는 형식입니다. 이유는 관리하기가 편해서? )

[file : abc.h]

#ifndef __ABC_H__
#define __ABC_H__

extern "C"
{//<-- extern 시작

#include "sysconfig.h"
#include "hello.h"
#include "test.h"

//function prototype
int abc(int a,int b); //abcii 라는 mangled 된 이름을 symbol로 가지게 됩니다.
int def(int a,int b);  // def 라는 symbol을 가지게 되는 것입니다.


}//extern 끝

#endif //__ABC_H__

자!! 이제 위와 같은 포멧으로 주로 많이들 사용하는데, 위의 내용을 보면 어떤가요? 문제가 있어보이나요 없어보이나요?

얼핏 보기엔 아무런 문제가 없어 보입니다.
하지만!!!!!

한가지 찾아낸 분이 있군요.... 그렇숩니다. ^^a 위의 해더파일은 C 파일에서는 include 해서 사용할 수 없습니다.

#include "abc.h"



int main()
{
  int a = abc(1,2);
}


이유는 extern "C" 는 C++ compiler에서만 지원하기 때문입니다. 
a.c 에서 #include "abc.h"를  사용하면 error가 발생합니다. 
그래서 

#ifdef __cplusplus 를 이용해서 extern "C" 를 묶어서 사용합니다. 

 

[file : abc.h]

#ifndef __ABC_H__
#define __ABC_H__

#ifdef __cplusplus 
extern "C" {//<-- extern 시작
#endif
#include "sysconfig.h"
#include "hello.h"
#include "test.h"

//function prototype
int abc(int a,int b); //abcii 라는 mangled 된 이름을 symbol로 가지게 됩니다.
int def(int a,int b);  // def 라는 symbol을 가지게 되는 것입니다.

#ifdef __cplusplus 
}//extern 끝
#endif
#endif //__ABC_H__

이렇게 사용함으로 해서 C compiler에서는 extern "C"를 사용하지 않고 compile됩니다.
C compiler에서는 c니까 당연히 name mangling이 발생하지 않겠죠.!!!! <-- 요거 중요한 예기...


자 그럼 두번째 문제점은 어디에 있을까요??
못찾겠죠... 흔히들 실수 할 수 있는 부분입니다.

( 찾았다구요?? 이 글 왜 읽고 있습니까?? 자리로 돌아가서 일하세요.. ㅎㅎ 다 아시는 분이.. ~~)

두번째 문제는 사실 편하게 쓰고자 extern "C" {} 를 사용하는데 이게 아래와 같이 사용하면 문제를 만듭니다. 무슨 말이냐 하면.. extern "C" {} 중간에 header file을 포함하고 있죠??

그래서 abc.h 가 sysconfig.h를 include 하고 있고, sysconfig.h는 def.h를 include하고 있다면,
extern "C"{ //<-- abc.h
    extern "C" { //<--sysconfig.h
           extern "C"{//<-- sysconfig.h 내에서 include 하고 있는 def.h
 
런 형식으로 가다가 결국 extern "C"가 너무 많이 중복 사용되었다는 에러메세지를 받고 당황하게 되실 것입니다. ㅎ
 
결국 VC에서는 아래와 같은 에러를 내면서 컴파일 에러를 냅니다.
fatal error C1045: compiler limit : linkage specifications nested too deeply
visual Studio 에서는 depth 제한이 10으로 되어있습니다.
 
그래서 당황하여 여기저기 extern "C"를 찾아서 지우고 옮기고 하다보면, 나중에 name mangling 되어 link error를 메세지를 받고 뒷목을 붙잡고 쓰러질 수도 있습니다.
이래서 어설프게 알고 사용하면 절대 안된다는 의미입니다.
저는 그래서 아래와 같이 header file 선언부 아래에 extern "C"를 사용하기를 권합니다.

 

[file : abc.h]

#ifndef __ABC_H__
#define __ABC_H__


#include "sysconfig.h"
#include "hello.h"
#include "test.h"

#ifdef __cplusplus 
extern "C" {//<-- extern 시작
#endif 
//function prototype
int abc(int a,int b); //abcii 라는 mangled 된 이름을 symbol로 가지게 됩니다.
int def(int a,int b);  // def 라는 symbol을 가지게 되는 것입니다.

#ifdef __cplusplus 
}//extern 끝
#endif
#endif //__ABC_H__

모든 header file들이 위와 같이 include file 아래서 부터 extern "C"를 사용하면, 아래와 같이 중복되지 않게 되어 depth가 늘어나지 않습니다.  <-- 요거 꽤 중요한 팁이니 자기가 맡고 있는 프로젝트가 있다면 한번 살펴보세요!! ㅎ

extern "C"
{//<-- sysconfig.h 내에서 include 하고 있는 def.h
}
extern "C" 
{ //<--sysconfig.h
}
extern "C"
{ //<-- abc.h
           :
           :
}


자!! 이제 가장 중요하고 핵심이 되는 문제가 남았습니다.

이 문제는 위에 있는 해더파일 내용으로만 봐서는 절대로 찾을 수 없는 내용인데요..

뭐냐하면..

위와 같이 header 파일을 잘 만들었다 하더라도 link error를 당할 수 있는 경우가 있다는 것입니다.!!

어떤 경우일까요? 흠흠.


어떤 경우냐 하면 ,  우리가 만든 abc 와 def 함수의 몸체는 abc.cpp 에 있죠?
function name 이 mangling 될때가 언제라고 했죠?
link 할때? 아니죠~~ compile 할때.. 즉 compiler가 abc.o를 만들때 name이 mangling됩니다.
즉, name mangling을 막을려면 abc.cpp가 compile될때 막아야 합니다.
즉 그말은 abc.cpp가 compile될때 이미 extern "C"가 함수들에 선언 되어 있어야 name mangling을 막을 수 있다는 예기 입니다.

이미 abc.h에 extern "C"로 잘 감싸 놨는데 무슨 예기냐 ~~ 모르겠다... 하시는 분들 계실 겁니다.

abc.cpp가 아래와 같이 extern "C"가 없다고 합시다. 그리고 main.c에서 아래와 같이 abc를 사용했다고 합시다.


[file : abc.cpp]

int abc(int a,int b) //abcii 라는 mangled 된 이름을 symbol로 가지게 됩니다.
{
return 0;
}

int def(int a,int b)  // defii 라는 symbol을 가지게 되는 것입니다.
{
return 0;
}

[file : main.c]

#include "abc.h"  //<-- error 발생

void main()
{
    abc(10,20);
}
아.. 하시는 분 있을거 같은데 ㅎㅎㅎ. 좀 감이 오시나요? 어쨌든 설명을 이어 가겠습니다.

main 에서 abc를 호출하면 main은 c 파일이기 때문에 mangliing 안된 abc 를 symbol로 link 합니다.

하지만 abc.cpp를 compiler가 컴파일 할때는 abcii, defii 로 mangling 된 이름으로 symbol을 만듭니다.
왜? abc.cpp를 보십시오. abc.cpp안에는 어디에도 extern "C"라고 선언된 부분이 없습니다.
그래서 C++ compiler는 함수 이름을 mangling해버립니다.
그래서 main에서 부른 abc는 symbol만있고 body가 없기 때문에 link 시에 에러가 발생합니다.

이제 아셨죠.?? 이런 정확한 메카니즘을 모르면 왜 링크에러나는지 모르고 이것 저것 삽질하다 수정되면 그냥 넘어가 버리게 됩니다.!!! 코드만 지저분해지게 만들구요..

그러면 abc, def가  mangling 안되게 만들려면 어떻게 할까요? 맨 위에 예제 처럼 cpp 파일 처음부터 끝까지 extern "C"로 감싸면 될까요?
제가 적극 추천하는 방법은  abc.h를 abc.c 에서 include 하는 방법을 추천합니다.

[file : abc.cpp]

#include "abc.h"


int abc(int a,int b) //_abc 라는 mangled 된 이름을 symbol로 가지게 됩니다.
{
return 0;
}

int def(int a,int b)  // _def 라는 symbol을 가지게 되는 것입니다.
{
return 0;
}

이렇게 하면 compiler가 abc.cpp 를 컴파일 할때 abc.h에 있는 extern "C"{} 로 되어있는 영역 내부의 내용에 해당하는 abc,def함수들을 모두 mangling안되게 해준답니다. 


3.마치며!!

항상 강조하지만 100% 이해하지 못하는 code나 함수를 내 프로그램에 추가하게 되면 반드시 그 대가를 치르게 됩니다.!!! 이는 불변의 진리입니다.!!!
그러니 여러분들도 "남들이 이렇게 쓰니 나도 이렇게 써야지 " 이렇게 하지 마시고, 자신이 사용하고자 하는 것에 대한 내용을 최대한 깊게 이해하려고 노력하십시오.

그러면 나중에 돌아올 부메랑을 막을 방법도 갖게 될 것입니다.!!

 

 

'개발 Note > it 이야기' 카테고리의 다른 글

Modal의 구현 형태  (0) 2009.01.12
UI Modal 컨셉  (0) 2009.01.06
Feature modeling - 아직 정리되지 않은 주제.  (0) 2009.01.04
Refactoring  (0) 2009.01.04
S60 platform architecture  (0) 2009.01.04

+ Recent posts