C++에서 C에 함수를 사용시 주의해야하는 사항이 있다. 아무 생각없이 C 함수를 사용한다면, 무시무시한 링크오류의 늪에 빠져들고 만다. 늪에 빠져든다고 해도 정신만 차리면 나올 수 있다.
작성일: 2009.09.02 (http://ospace.tistory.com/), ospace114@empal.com
단순히 링크 오류에 대해서만 찾고 계신다면 혹시 아래와 같은 상황이라면 이 글을 읽어보길 바란다.
- C++ 프로그래밍을 하고 있고 다른 곳에 예제를 그대로 사용하고 있는데 링크에러가 뜬다.
- include나 lib 폴더도 정확하고 불러오는 라이브러리 파일도 정확한데 링크에러가 뜬다.
- 컴파일러 옵션이나 링크 옵션도 이리저리 바꿔보아도 링크에러가 뜬다.
- 다른 함수는 이상이 없는데 특정 일부 함수만 링크에러가 뜬다.
- 지금 사용하는 라이브리가 C용 라이브러리이다.
링크오류
VC++에서는 이런 링크 오류가 LNK2019로 표시된다. 물론 반드시 이렇다는 것은 아니다.
Server.obj : error LNK2019: unresolved external symbol "void __cdecl event_err(int,char const *,...)" (?event_err@@YAXHPBDZZ) referenced in function "void __cdecl on_accept(int,short,void *)" (?on_accept@@YAXHFPAX@Z)
위는 본인이 경험했던 오류이다. 이 문제를 해결하려면 아래 내용을 읽어보길 바란다.
C++에서 C 함수 사용하기
C++에서 컴파일된 함수 정의와 C에서 컴파일된 함수 정의는 다르다. 같은 함수 이름을 정의해도 다른 함수로 인식하여 사용하게 된다. 물론 C와 C++에서 같은 이름을 가진 함수가 있을 수 있지만, 이렇게 하면 나중에 혼란이 발생할 우려가 있으니 사용하면 안되겠지만...
C++에서 C++함수 사용은 당연히 문제가 없다. 그러나 C++에서 C 함수 사용함에 있어서 C 헤더 파일 정의를 주의해야한다.
그럼 C 헤더 파일 정의는 어떻게 될까?
// sample.h
#ifdef __cplusplus
extern "C" {
#endif
void event_err(int eval, const char *fmt, ...);
//... (중략)
#ifdef __cplusplus
};
#endif
위와 같이 정이하면 된다. 즉 "__cplusplus"는 C++ 컴파일러를 사용하고 있다는 의미이다.
그래서 C++이라면 extern "C"를 사용해서 선언하면 된다. 간단하게 사용하면,
extern "C" void event_err(int eval, const char *fmt, ...);
처럼 사용할 수 있다. C++과 C를 선택적으로 호환 가능한 헤더 파일을 만들기 위해서 #ifdef 전처리기를 사용해서 선택적으로 선언해서 사용하는 것이 좋다.
추가적인 해결 방안
만약에 기존 소스 코드를 수정해야 하는데, 내가 건드릴 수 없거나, 아니면 수정할 권한을 가지고 있지 않다면 위의 방법과 같이 수정할 수 없다.
그럼 어떻게 할까?
방법은 다른 헤더파일을 만들어서 거기서 c헤더 파일을 불러 오고 __cplusplus 전처리기를 추가한다. 예를 들어 "c_api.h"라는 헤더 파일이 있다고 하자. 그러면 "cpp_api.h"파일을 만들어서 아래와 같이 작성한다.
//cpp_api.h file
#ifndef __CPP_API_H__
#define __CPP_API_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <c_api.h> //이부분은 헤더 파일 위치에 따라서 변경될 수 있다.
#ifdef __cplusplus
}
#endif
#endif
생각보다 쉽다. ^^;
결론
링크에러 2019의 실제 에러는 "unresolved external symbol 'symbol' referenced in function 'function'"이다. 즉, 선언한 함수에 대한 실제 구현 부분을 찾을 수 없다는 말이다. 물론 이런 에러가 발생할 경우는 무지 많다.
필자가 위에서 설명한 부분도 그 중에 하나일 뿐이다. 단지 그외의 경우는 이것 저것 하면서 쉽게 찾거나 좀만 하면 해결할 수 있지만, 이 경우는 간단하지만 간과하기 쉬운 부분이다.
C++에서 C 함수를 사용하는 것은 잘 알고 있었던 내용이다. 그러나 링크에러가 발생하고, 단순히 라이브러리 링크에 문제가 있다고, 컴파일러에 문제가 있다고, 아니면 설정에 문제가 있다고만 생각한 것이 큰 실수 였다.
이로 인해 내가 몇시간이라는 귀중한 시간을 소비해버렸다. 정말 짜증이 해일 처럼 밀려온다.
그렇게 해서 혹시 같은 어려움을 갖고 있는 분들에게 도움이 되려고 내용을 작성하였다. 물론 링크 오류외에 C++에서 C함수를 사용하는 내용도 있으나, 그 내용말고 링크 오류에 대한 내용도 같이 참고하면 나중에 도움이 되리라 생각한다.ospace.
'3.구현 > C or C++' 카테고리의 다른 글
C에서 C++ 호출하기 (0) | 2010.11.30 |
---|---|
데이터 값을 비트 문자열로 변환 (0) | 2009.12.23 |
C로 객체지향 흉내내기2 (0) | 2009.07.27 |
C로 객체지향 흉내내기1 (0) | 2009.07.23 |
Morden Programming의 Functor (0) | 2009.03.08 |