2014년 10월 29일 수요일

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

원본글 : http://ospace.tistory.com/187

C소스를 C++(MFC) 프로젝트에 붙여야 될 일이 있었는데, 계속 LNK2019 링킹에러가 발생하였다. 강제로 obj파일을 링크 걸으면 이미 구현되어 있다고 에러를 뿜어내고 참 난감했는데....해결 방법은 다른 곳에 있었다. 출처는 위 주소.



======================================================================================================================

들어가기



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

댓글 없음: