C ++ 코드에서 C 함수 호출


90

C ++에서 호출하고 싶은 C 함수가 있습니다. extern "C" void foo()C 함수가 g ++를 사용하여 컴파일되지 않았기 때문에 " "종류의 접근 방식을 사용할 수 없습니다 . 그러나 gcc를 사용하여 잘 컴파일됩니다. C ++에서 함수를 호출하는 방법에 대한 아이디어가 있습니까?


1
당신은 몇 가지 예제 코드 및 쓰기 시겠어요 g++오류 메시지
마티유 Rouget에게

7
C ++ 컴파일러로 컴파일하면 C ++입니다. C 코드는 C ++ 컴파일러로 컴파일 할 필요가 없습니다. 그들은 다른 언어입니다. 코드가 유효한 C ++가 아니므로 C ++ 컴파일러로 컴파일되지 않습니다.
xaxxon

3
@MatthieuRougetvoid valid_in_C_but_not_in_CPlusPlus(size_t size) { char variable_length_array[size]; }
자폐증

2
내 시도 : void f(void *pv) { int *pi = pv; *pi = 42; }^^
gx_ 2013 년

1
특히 C (C ++가 아닌) 컴파일러를 C 코드에 사용할 수있는 방법을 지적하는 좋은 답변이 있기 때문에 열어 두어야합니다.
Chris Stratton

답변:


126

다음과 같이 C 코드를 컴파일합니다.

gcc -c -o somecode.o somecode.c

그런 다음 다음과 같은 C ++ 코드 :

g++ -c -o othercode.o othercode.cpp

그런 다음 C ++ 링커를 사용하여 함께 연결합니다.

g++ -o yourprogram somecode.o othercode.o

또한 C 함수에 대한 선언을 포함 할 때 C 헤더가 올 것이라고 C ++ 컴파일러에 알려야합니다. 따라서 다음으로 othercode.cpp시작합니다.

extern "C" {
#include "somecode.h"
}

somecode.h 다음과 같은 내용을 포함해야합니다.

 #ifndef SOMECODE_H_
 #define SOMECODE_H_

 void foo();

 #endif


(이 예제에서는 gcc를 사용했지만 원칙은 모든 컴파일러에서 동일합니다. 각각 C와 C ++로 개별적으로 빌드 한 다음 함께 연결합니다.)


7
@Arne 좋은 포인트. 어떤 사람들 extern "C"은 헤더를 #ifdef __cplusplus.
언 와인드

@Arne 아래 내 대답을 참조하십시오. 당신이 볼 수 있듯이 나는 그들 중 하나입니다;)
gx_

1
정말 고맙습니다 ! 즉 :) 나에게 매우 유용
헤샴 Eraqi

다음과 같은 오류가 발생했습니다. 오류 : # 337 : 연결 사양이 이전 "foo"(1 줄에 선언 됨)와 호환되지 않습니다. 이제 컴파일이 괜찮습니다. 누구든지 설명 할 수 있습니까?
FaizanHussainRabbani

@FaizanRabbani, 더 많은 세부 사항 없이는 아닙니다.
Prof. Falken

61

명확하게 분리 된 C 및 C ++ 코드로 예제를 제공하기 위해 다른 답변과 주석에서 비트와 조각을 수집하겠습니다.

C 부분 :

foo.h :

#ifndef FOO_H
#define FOO_H

void foo(void);

#endif 

foo.c

#include "foo.h"

void foo(void)
{
    /* ... */
}

이것을 gcc -c -o foo.o foo.c.

C ++ 부분 :

bar.cpp

extern "C" {
  #include "foo.h" //a C header, so wrap it in extern "C" 
}

void bar() {
  foo();
}

이것을 컴파일 g++ -c -o bar.o bar.cpp

그런 다음 모두 함께 연결합니다.

g++ -o myfoobar foo.o bar.o

근거 : C 코드는 일반 C 코드 여야하며 #ifdef"언젠가 다른 언어에서이 코드를 호출 할 것입니다."라는 의미가 아닙니다 . 일부 C ++ 프로그래머가 C 함수를 호출하면, 그건 자신의 , 당신이하지 수행하는 방법 문제. 그리고 만약 당신이 C ++ 프로그래머라면, C 헤더는 당신의 것이 아닐 수도 있고 당신은 그것을 변경해서는 안됩니다. 따라서 얽 히지 않은 함수 이름 (예 :)의 처리는 extern "C"C ++ 코드에 속합니다.

물론 C 헤더를 extern "C"선언 으로 래핑하는 것 외에는 아무것도하지 않는 편리한 C ++ 헤더를 직접 작성할 수도 있습니다 .


7
합법적 인 것 같습니다. 근거에 대한 +1
gx_ 2013 년

마지막으로 이것에 대한 완전히 명확한 설명. 엄청 고마워!
Daniel Soutar 2018

16

나는 Prof. Falken의 대답에 동의 하지만 Arne Mertz의 의견에 따라 완전한 예를 들었습니다 (가장 중요한 부분은 #ifdef __cplusplus).

somecode.h

#ifndef H_SOMECODE
#define H_SOMECODE

#ifdef __cplusplus
extern "C" {
#endif

void foo(void);

#ifdef __cplusplus
}
#endif

#endif /* H_SOMECODE */

somecode.c

#include "somecode.h"

void foo(void)
{
    /* ... */
}

othercode.hpp

#ifndef HPP_OTHERCODE
#define HPP_OTHERCODE

void bar();

#endif /* HPP_OTHERCODE */

othercode.cpp

#include "othercode.hpp"
#include "somecode.h"

void bar()
{
    foo(); // call C function
    // ...
}

그런 다음 Falken 교수의 지시에 따라 컴파일하고 연결합니다.

로 컴파일 할 때 gcc매크로 __cplusplus가 정의되지 않았으므로에 somecode.h포함 된 헤더 somecode.c는 전처리 후 다음 과 같기 때문에 작동합니다 .

void foo(void);

컴파일 할 때 g++, 다음 __cplusplus 되고 정의하고,에 포함 된 헤더 때문에 othercode.cpp지금과 같다 :

extern "C" {

void foo(void);

}

4
thb, 나는 #ifdef __cplusplusC 코드를 좋아하지 않습니다 . C 코드는 하위 수준이며 언젠가 C ++ 코드에서 호출 될 수있는 경우 신경 쓸 필요가 없습니다. #ifdefC ++로 작성된 라이브러리에 대한 C 바인딩 헤더를 제공하려는 경우 C ++ 코드에서만 사용되는 Imo .
Arne Mertz

2
물론 @ Prof.Falken은 C 코드가 아닌 C ++ 코드의 "하향"호환성을 제공 할 수 있도록 정의한 것입니다.
Arne Mertz

1

이 답변은 Arne의 근거가 올바른 경우에서 영감을 얻었습니다. 한 공급 업체가 한때 C와 C ++를 모두 지원하는 라이브러리를 작성했습니다. 그러나 최신 버전은 C 만 지원했습니다. 코드에 남겨진 다음 흔적 지시문은 오해의 소지가 있습니다.

#ifdef __cplusplus
extern "C" {
#endif

이로 인해 C ++로 컴파일하는 데 몇 시간이 소요되었습니다. 단순히 C ++에서 C를 호출하는 것이 훨씬 쉬웠습니다.

ifdef __cplusplus 규칙은 단일 책임 원칙을 위반합니다. 이 규칙을 사용하는 코드는 한 번에 두 가지 작업을 수행하려고합니다.

  • (1) C에서 함수 실행-및-
  • (2) C ++에서 동일한 기능 실행

미국식 영어와 영국식 영어를 동시에 쓰려고하는 것과 같습니다. 이것은 불필요하게 #ifdef __thequeensenglish 스패너 #elif __yankeeenglish 렌치 #else 코드를 코드로 읽기 어렵게 만드는 쓸모없는 도구입니다.

간단한 코드와 작은 라이브러리의 경우 ifdef __cplusplus 규칙이 작동 할 수 있습니다. 그러나 복잡한 라이브러리의 경우 한 언어 또는 다른 언어를 선택하고 그대로 유지하는 것이 가장 좋습니다. 언어 중 하나를 지원하는 것은 둘 다 지원하는 것보다 유지 관리가 덜 필요합니다.

이것은 Ubuntu Linux에서 컴파일하기 위해 Arne의 코드를 수정 한 기록입니다.

foo.h :

#ifndef FOO_H
#define FOO_H

void foo(void);

#endif 

foo.c

#include "foo.h"
#include <stdio.h>

void foo(void)
{
     // modified to verify the code was called
     printf("This Hello World was called in C++ and written in C\n");
}

bar.cpp

extern "C" {
    #include "foo.h" //a C header, so wrap it in extern "C" 
}

int main() {
  foo();
  return(0);
}

Makefile

# -*- MakeFile -*-
# dont forget to use tabs, not spaces for indents
# to use simple copy this file in the same directory and type 'make'

myfoobar: bar.o foo.o
    g++ -o myfoobar foo.o bar.o 

bar.o: bar.cpp
    g++ -c -o bar.o bar.cpp

foo.o: foo.c
    gcc -c -o foo.o foo.c
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.