(VS C/C++) C에서 C++로 만든 외부 파일의 함수를 링크 참조 실행하기, C에서C는 extern C에서C++는 extern “C”

visual studio c/c++, gcc,c++ C/C++언어

C에서 C로 만든 외부 파일의 함수를 링크 참조 실행하는 코드은 어렵지않게 만들수 있습니다만 C에서 C++로 만든 외부 파일의 함수를 링크 참조 실행하는 경우 “error LNK2019: sub001 main 함수에서 참조되는 확인할 수 없는 외부 기호” , “fatal error LNK1120: 1개의 확인할 수 없는 외부 참조입니다.” 오류가 발생하는 경우가 있습니다. 이 글에서는 오류를 해결하는 방법에 대해서 소개합니다.

중요 포인트

C(.c파일)에서는 “C 결합” 만 빌드할 수 있습니다.
C++(.cpp파일)에서는 “C 결합/C++ 결합” 둘다 빌드 할 수 있습니다.
C++(.cpp파일)에서 extern “C”는”C 결합“을 extern은 “C++ 결합“을 의미합니다.
C++로 작성한 함수를 C코드에서 참조하려면 C 결합” 빌드를 해야 하므로 extern 선언 대신에 extern “C” 로 변경해야 합니다.

컴파일 환경

이 글에서 작성된 코드는 Microsoft Visual Studio Community 2022 (64-bit) 버전 17.0.4 Microsoft Visual C++ 2022에서 다음과 같은 옵션으로 빌드(컴파일 & 결합) 되었습다.

컴파일 옵션

/JMC /permissive- /ifcOutput "C:\MySolution\SAMPLE01\\Debug_x64\" /GS 
/W3 /Zc:wchar_t /ZI /Gm- /Od /sdl /Fd"C:\MySolution\SAMPLE01\\Debug_x64\vc143.pdb" 
/Zc:inline /fp:precise 
/D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt 
/WX- /Zc:forScope /RTC1 /Gd /MDd /FC 
/Fa"C:\Users\admin\source\repos\MySolution\SAMPLE01\\Debug_x64\" /EHsc /nologo 
/Fo"C:\MySolution\SAMPLE01\\Debug_x64\" 
/Fp"C:\MySolution\SAMPLE01\\Debug_x64\SAMPLE01.pch" /diagnostics:column 

링커 옵션

/OUT:"C:\MySolution\SAMPLE01\\Debug_x64\SAMPLE01.exe" 
/MANIFEST /NXCOMPAT 
/PDB:"C:\SAMPLE01\\Debug_x64\SAMPLE01.pdb" 
/DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" 
/DEBUG /MACHINE:X64 
/INCREMENTAL 
/PGD:"C:\SAMPLE01\\Debug_x64\SAMPLE01.pgd" 
/SUBSYSTEM:CONSOLE 
/MANIFESTUAC:"level='asInvoker' uiAccess='false'" 
/ManifestFile:"C:\SAMPLE01\\Debug_x64\SAMPLE01.exe.intermediate.manifest" 
/LTCGOUT:"C:\SAMPLE01\\Debug_x64\SAMPLE01.iobj" 
/ERRORREPORT:PROMPT 
/ILK:"C:\SAMPLE01\\Debug_x64\SAMPLE01.ilk" 
/NOLOGO 
/TLBID:1 

C에서 C로 만든 외부 파일의 함수 링크 참조 실행하기

다음과 같이 sample01_sub.c 의 함수 sub001()을 sample01_main.c에서 실행하는 코드는 다음과 같습니다.

sample01_main.c

#include <stdio.h>
int sub001(); //외부 함수 선언 "C결합"
int main(int argc, char** argv) {
    return sub001();
}

sample01_sub.c

#include <stdio.h>
extern int sub001(); //외부 에서 링크 참조 할 수 있도록 선언. "C결합"
int sub001() {
    printf("test\n");
    return 1;
}

컴파일 결과는 다음과 같습니다.

빌드 시작...
1>------ 빌드 시작: 프로젝트: SAMPLE01, 구성: Debug x64 ------
1>sample01_main.c
1>sample01_sub.c
1>코드를 생성하고 있습니다...
1>SAMPLE01.vcxproj -> C:\MySolution\SAMPLE01\Debug_x64\SAMPLE01.exe
========== 빌드: 성공 1, 실패 0, 최신 0, 생략 0 ==========

실행 결과는 다음과 같습니다.

C:\MySolution\SAMPLE01\Debug_x64>sample01.exe
test
C:\MySolution\SAMPLE01\Debug_x64>echo %errorlevel%
1

C에서 C++로 만든 외부 파일의 함수 링크 참조 실행하기

C 코드 printf(“test\n“);를 C++코딩 기법의 std::cout << “test” << std::endl; 로 변경한다면 sample01_sub.csample01_sub.cpp로 다음과 같이 이름을 변경하여 컴파일 합니다.

sample01_main.c

#include <stdio.h>
int sub001();//외부 함수 선언 "C결합"
int main(int argc, char** argv) {
	return sub001();
}

sample01_sub.cpp

#include <iostream>
extern int sub001(); //외부 에서 링크 참조 할 수 있도록 선언."C++ 결합"
int sub001() {
	std::cout << "test" << std::endl;
	return 1;
}

참조에 관련된 선언이 C코드에서 변경이 없음에도 불구 하고 “C결합” 과 “C++ 결합” 의 차이로 컴파일 결과는 다음과 같이 링크 실패로 끝났음을 확인 할 수 있습니다.

빌드 시작...
1>------ 빌드 시작: 프로젝트: SAMPLE01, 구성: Debug x64 ------
1>sample01_main.c
1>sample01_sub.cpp
1>sample01_main.obj : error LNK2019: sub001 main 함수에서 참조되는 확인할 수 없는 외부 기호
1>  정의되었으며 잠재적으로 일치할 수 있는 기호에 대한 힌트:
1>    "int __cdecl sub001(void)" (?sub001@@YAHXZ)
1>C:\Users\admin\source\repos\MySolution\SAMPLE01\\Debug_x64\SAMPLE01.exe : fatal error LNK1120: 1개의 확인할 수 없는 외부 참조입니다.
1>"SAMPLE01.vcxproj" 프로젝트를 빌드했습니다. - 실패
========== 모두 다시 빌드: 성공 0, 실패 1, 생략 0 ==========

C++함수를 extern “C”로 변경 “C 결합” 빌드

다음과 같이 C코드에서 참조할 수 있도록 extern “C”로 변경해서 “C 결합” 빌드 합니다.

sample01_main.c

#include <stdio.h>
int sub001(); //외부 함수 선언 "C결합"
int main(int argc, char** argv) {
    return sub001();
}

sample01_sub.cpp

#include <iostream>
extern "C" int sub001();//외부 에서 참조 할 수 있도록 선언. "C결합"
int sub001() {
	std::cout << "test" << std::endl;
	return 1;
}

컴파일 결과는 다음과 같습니다.

빌드 시작...
1>------ 빌드 시작: 프로젝트: SAMPLE01, 구성: Debug x64 ------
1>sample01_sub.cpp
1>SAMPLE01.vcxproj -> C:\Users\admin\source\repos\MySolution\SAMPLE01\Debug_x64\SAMPLE01.exe
========== 빌드: 성공 1, 실패 0, 최신 0, 생략 0 ==========

실행 결과는 다음과 같습니다.

C:\MySolution\SAMPLE01\Debug_x64>sample01.exe
test
C:\MySolution\SAMPLE01\Debug_x64>echo %errorlevel%
1
제목과 URL을 복사했습니다