본문 바로가기

Stupid Computer/2. C 언어

[링크에러 LNK2019] C++에서 C 함수 사용하기

출처 : http://ospace.tistory.com/187


들어가기

C++에서  C에 함수를 사용시 주의해야하는 사항이 있다. 아무 생각없이 C 함수를 사용한다면, 무시무시한 링크오류의 늪에 빠져들고 만다. 늪에 빠져든다고 해도 정신만 차리면 나올 수 있다.

단순히 링크 오류에  대해서만 찾고 계신다면 혹시 아래와 같은 상황이라면 이 글을 읽어보길 바란다.

  • 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 헤더 파일 정의는 어떻게 될까?

// 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함수를 사용하는 내용도 있으나, 그 내용말고 링크 오류에 대한 내용도 같이 참고하면 나중에 도움이 되리라 생각한다.

헤더 파일로 추가하니까 훨씬 편하네요 !