C 코드에서 C ++ 라이브러리 사용


102

데이터 관리를위한 다양한 클래스를 제공하는 C ++ 라이브러리가 있습니다. 라이브러리의 소스 코드가 있습니다.

라이브러리를 C 코드와 C ++ 코드와 동시에 사용할 수 있도록 C 함수 호출을 지원하도록 C ++ API를 확장하고 싶습니다.

GNU 도구 체인 (gcc, glibc 등)을 사용하고 있으므로 언어 ​​및 아키텍처 지원이 문제가되지 않습니다.

이것이 기술적으로 불가능한 이유가 있습니까?

주의 해야 할 문제가 있습니까?

이와 관련하여 사용할 수있는 리소스, 예제 코드 및 / 또는 문서가 있습니까?


내가 알아 낸 다른 것 :

  1. 다음을 사용하여 C 코드에서 사용해야하는 C ++ 헤더를 래핑합니다.

#ifdef __cplusplus
extern "C" {  
#endif  
//  
// Code goes here ...  
//  
#ifdef __cplusplus  
} // extern "C"  
#endif
  1. C에 포함되지 않은 별도의 헤더 파일에 "실제"C ++ 인터페이스를 유지합니다. Think PIMPL 원칙 하십시오. 여기서 하십시오. #ifndef __cplusplus #error여기서 물건을 사용하면 광기를 감지하는 데 도움이됩니다.
  2. C 코드에서 이름으로 C ++ 식별자에주의
  3. C 및 C ++ 컴파일러간에 크기가 다른 열거 형입니다. GNU 도구 체인을 사용하는 경우 문제가되지 않지만 여전히 조심하십시오.
  4. 구조체의 경우 C가 혼동되지 않도록 다음 형식을 따르십시오.

    typedef struct X { ... } X
  5. 그런 다음 C ++ 개체를 전달하기 위해 포인터를 사용합니다. C에서 X가 C ++ 개체 인 구조체 X로 선언되어야합니다.

이 모든 것은 C ++의 마법사 인 친구의 호의입니다.


5
다소 늦었지만 C ++ 용 C 래퍼에 대한 간단한
Teddy

답변:


69

예, 이것은 확실히 가능합니다. 다음을 사용하여 함수를 선언하는 인터페이스 레이어를 C ++로 작성해야합니다 extern "C".

extern "C" int foo(char *bar)
{
    return realFoo(std::string(bar));
}

그런 다음 foo()C 모듈에서 호출하여 realFoo()C ++로 구현 된 함수 에 호출을 전달합니다 .

데이터 멤버 및 메서드가있는 전체 C ++ 클래스를 노출해야하는 경우이 간단한 함수 예제보다 더 많은 작업을 수행해야 할 수 있습니다.


extern "C"정의가 아닌 선언에만 배치 해야합니까 ? "함수를 선언하는 계층"을 언급했지만 샘플 코드도 정의이기 때문입니다. 즉, 헤더 파일이나 소스 파일에 배치해야합니까? (또는 둘 다?)
kyriakosSt

@KyrSt : 함수 선언이있는 헤더 파일이 있다면 적어도 extern "C"거기에 넣어야 합니다. 컴파일러는 정의에 넣어야하는지 여부를 알려줍니다.
Greg Hewgill

23

C ++ FAQ Lite : "C 및 C ++ 코드 혼합 방법" .

다음 질문에 대한 답변에 몇 가지 문제점이 설명되어 있습니다.

  • [32.8] C ++ 클래스의 객체를 C 함수로 /로부터 어떻게 전달할 수 있습니까?
  • [32.9] 내 C 함수가 C ++ 클래스의 객체에있는 데이터에 직접 액세스 할 수 있습니까?

12

주요 문제점 : C에서는 예외를 포착 할 수 없습니다. C ++ 코드에서 예외가 발생할 가능성이있는 경우 C 코드 또는 C ++ 래퍼를 매우 신중하게 작성하십시오. 반대로, C 코드 (다양한 스크립팅 언어에서 볼 수있는)의 예외와 같은 메커니즘 (예 : longjump)은 스택에서 C ++ 객체에 대한 소멸자를 호출하는 데 필요하지 않습니다.


2
longjump 호출에 대한 좋은 점. 직접 사용하지는 않지만 내가 사용하는 테스트 프레임 워크가이를 구현합니다. 명심해야 할 것. 감사합니다
Misha M

3

C / C ++ 코드를 혼합 할 수 있습니다. C ++에서 main () 함수를 사용하는 경우 c 함수가 선언되었는지 확인하기 만하면됩니다.

extern "C"

메인이 C이면 정적 변수를 제외하고는 괜찮습니다. 정적 변수가있는 모든 생성자는 main () 시작 전에 호출되어야합니다. C가 메인 인 경우에는 발생하지 않습니다. 많은 정적 변수가 있습니다. 가장 좋은 방법은 정적 변수를 싱글 톤으로 바꾸는 것입니다.

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