C는 왜 C ++가 부족한 언어 '바인딩'을 제공합니까?


60

최근에 C를 C ++보다 언제 사용할 것인지 궁금해 하고 있었습니까? 다행스럽게도 누군가 이미 저를 이겼고 시간이 걸렸지 만 그 질문에 대한 모든 답변과 의견을 요약 할 수있었습니다.

그러나 해당 게시물의 한 항목은 어떤 종류의 예나 확인이나 설명없이 계속해서 반복해서 다루어집니다.

"C 코드는 라이브러리에 여러 언어 바인딩을 원할 때 유용합니다."

그것은 역설이다. 몇몇 사람들은 C ++에서 (일부 extern기능을 통해 ) 다중 언어 바인딩이 가능하다는 것을 지적 하지만 그럼에도 불구하고 그 게시물을 완전히 읽으면 C가 이식성 / 언어 바인딩에 이상적이라는 것이 분명합니다. 내 질문은 : 왜?

누군가 C 언어로 라이브러리를 작성하면 다른 언어로 쉽게 바인딩하거나 이식 할 수있는 구체적인 이유를 알려줄 수 있습니까?


6
대부분 역사적, 사회적 이유로. 대부분의 언어 구현 및 런타임 시스템은 C를 기반으로 구축됩니다. 예를 들어, Ocaml, SBCL, Haskell 런타임은 C로 코딩되며 C ++로 코딩 되어도 크게 향상되지 않습니다.
Basile Starynkevitch

8
실제로, 실제 C ++ 라이브러리 (Qt라고 생각)를 이러한 런타임에 붙이는 것은 고통 스럽습니다.
바 실레 Starynkevitch

3
@Basile : Qt는 C ++ 라이브러리가 아닙니다. 또한 더 고통스러운 라이브러리의 경우에도 실제로 유용한 의미를 표현하기 때문에 고통 스럽습니다.
DeadMG


2
Don Box의 필수 COM을 읽으십시오. C ++로 ABI를 생성하는 과정을 설명합니다. COM은 Microsoft의 ABI 작성 방법이었습니다. 즉 COM C ++ 라이브러리는 C 또는 VB 또는 다른 언어에서 사용될 수 있습니다.
user93353

답변:


69

C는 훨씬 더 간단한 인터페이스를 가지고 있으며, 소스 코드 인터페이스를 이진 인터페이스로 변환하는 규칙은 간단하게 바인딩 할 외부 인터페이스를 생성하는 데 매우 간단합니다. 반면 C ++은 매우 복잡한 인터페이스를 가지고 있으며 ABI 바인딩 규칙은 공식적으로나 실제로 표준화되지 않았습니다. 이는 모든 플랫폼의 모든 언어에 대한 거의 모든 컴파일러가 외부 C 인터페이스에 바인딩되어 정확히 무엇을 알 수 있는지를 의미하지만 C ++ 인터페이스의 경우 규칙이 어떤 컴파일러, 버전 및 버전에 따라 변경되기 때문에 본질적으로 불가능합니다. C ++ 코드가 내장 된 플랫폼.

C에는 표준 이진 언어 구현 규칙이 없지만 훨씬 간단합니다. 실제로 컴파일러는 동일한 규칙을 사용합니다. C ++ 코드를 디버깅하기 어려운 또 다른 이유는 위에서 언급 한 복잡한 문법인데, 디버거는 종종 많은 언어 기능 (템플릿에 중단 점 배치, 데이터 표시 창에서 포인터 캐스팅 명령 구문 분석 등)을 처리 할 수 ​​없기 때문입니다.

표준 ABI (애플리케이션 바이너리 인터페이스)가 없으면 또 다른 결과가 발생합니다. 동일한 툴과 빌드 옵션으로 컴파일하지 않으면 사용자 코드가 작동하지 않기 때문에 다른 팀 / 고객에게 C ++ 인터페이스를 제공하는 것은 실용적이지 않습니다. 우리는 이미이 문제의 또 다른 원인 인 컴파일 시간 캡슐화가 없기 때문에 바이너리 인터페이스의 불안정성을 보았습니다.

- 결함이있는 C ++


4
C ++로 구현 된 C와 유사한 API를 정의하는 것이 가능하지만 (C ++ extern "C"이 제공하는 기능과 균형을 이루어야하는 추가 작업이 여전히 필요합니다)
jhominal

5
C ++ ABI는 질문과 관련이 없으며 C ++ 라이브러리를로 쉽게 내보낼 수 있습니다 extern "C".
DeadMG

12
@ jhominal : C로 작성하는 것보다 훨씬 낫습니다 .C 인터페이스를 정의한 다음 C로 구현해야하지만 C ++에서는 C 인터페이스를 정의 할 수 있으므로 구현 할 필요가 없습니다. 어떤 언어로 구현하든 C 인터페이스를 정의해야합니다. 물론 C 또는 C 바인딩을 노출시킬 수있는 다른 언어와 마찬가지로 C ++에서도 마찬가지입니다.
DeadMG

9
해당 FQA 드라이브 링크에 고지 사항을 추가 할 수 있습니까?
Martin Ba

2
@ DocBrown : 물론 C 언어 바인딩과 C ++ 언어 바인딩에 관한 질문 인 것처럼 보입니다.
메이슨 휠러

32

다른 언어로 말하는 사람과 의사 소통을하려는 경우, 셰익스피어 영어보다 피진 이 더 쉽습니다.

함수 호출, 포인터, NULL로 끝나는 문자열과 같은 C의 개념은 매우 간단하므로 다른 언어는 C 함수를 호출하기에 충분할 정도로 쉽게 구현할 수 있습니다. 역사적 이유로, 많은 다른 언어가 C로 구현되어 C 함수 호출이 훨씬 쉬워졌습니다.

C ++은 상속과 vtable, 액세스 수정자를 가진 클래스를 추가합니다. 스택 해제 및 제어 흐름 변경과 함께 예외; 템플릿. 이 모든 것이 다른 언어에서 C ++ 바인딩을 사용하기 어렵게 만듭니다. 기껏해야 구현할 "접착제"또는 상호 운용성 코드가 더 많으며 최악의 경우 개념이 직접 변환되지 않습니다 (클래스 모델의 차이, 예외 처리, 기타.). 특히 템플릿의 경우 단순히 사용 (인스턴스화)하면 일반적으로 C ++ 컴파일러를 사용하는 컴파일 단계가 필요합니다.이 단계 는 다른 환경에서 사용하기 가 상당히 복잡합니다.

이 모든 것을 말하면 C ++ 라이브러리에서 다른 언어로 바인딩을 제공하는 데 어려움을 과장 할 수 있습니다.

  • C ++ 바인딩은 기꺼이 작업하려는 경우 C와 마찬가지로 호환 될 수 있습니다. @DeadMG가 지적했듯이 C ++은을 지원 extern "C"하므로 C 스타일 라이브러리 (C 바인딩의 단순성과 호환성을 모두 갖춘)를 C ++ 라이브러리에서 내보낼 수 있습니다 (C ++ 관련 기능을 노출 할 수 없다는 제한이 있음) .
  • C ++ 언어 바인딩에 대한 또 다른 일반적인 반대 의견은 C ++에 대한 ABI 안정성이 부족하다는 것입니다. C ++ ABI는 C ABI보다 표준화 수준이 낮지 만 표준 및 사실상의 표준 (Itanium C ++ ABI는 OS X 에서도 사용됨 ; Linux 의 GCC의 사실상 표준 )이 있습니다. Windows는 더 나쁘지만 Windows에서도 Visual C ++ 버전 하나를 유지하는 것이 좋습니다.

1
C ++ 라이브러리에서 다른 언어로 바인딩을 제공하는 다른 문제 는 다른 언어로 C에서 바인딩을 구현해야 할 수도 있다는 것입니다. 또는 (.NET) P / Invoke 또는 (python) ctypes와 같은 언어의 경우 C ++ ABI 사용을 위한 도구를 제공하지 않을 수 있습니다 .
Random832

6
@ Random832 : C ++ 측이 단순히 C 인터페이스를 제공 할 수있을 때 전혀 관련이 없습니다. C 바인딩을 제공하기 위해 C에서 바인딩을 구현할 필요는 없습니다.
DeadMG

21

C는 여전히 가장 오래된 언어 중 하나입니다. ABI는 단순하며 오늘날에도 여전히 사용되고있는 거의 모든 운영 체제가 여기에 작성되었습니다 . 이러한 OS 중 일부는 C # / .NET 또는 맨 위에있는 항목을 추가했을 수 있지만 아래에서 C에서는 매우 가파 릅니다.

즉 , OS에서 제공하는 기능 을 사용 하려면 사실상 모든 프로그래밍 언어가 C 라이브러리와 인터페이스 할 수있는 방법이 필요했습니다 . Perl, Java, C ++는 모두 기본적으로 "토론 C"를 할 수있는 방법을 제공합니다. 왜냐하면 모든 휠을 재발 명하고 싶지 않다면 필요했습니다.

이것은 C를 프로그래밍 언어의 라틴어로 만듭니다. (비유가 나오기 전에 몇 년 동안 인터넷이 "프로 게밍 언어의 영어"여야합니까?)


C로 라이브러리를 작성하는 경우 C 호환 인터페이스가 무료로 제공됩니다. C ++로 라이브러리를 작성하는 경우 언급 한대로 선언을 통해 C 바인딩을 얻을 수 있습니다extern "C" .

그러나 C로 표현할 수있는 기능에 대해서만 바인딩을 얻을 수 있습니다 .

따라서 라이브러리 API는 사용할 수 없습니다 ...

  • 템플릿,
  • 클래스,
  • 예외
  • 객체를 가져 오거나 반환 하는 함수

간단한 예를 들어, 내 보낸 함수 배열 ( ) 대신 (또는 그 문제) 배열을 가져 오고 반환 하도록해야합니다 .[]std::vectorstd::string

따라서 C ++이 라이브러리 클라이언트에 제공해야하는 장점을 제공 할 수 없을 뿐만 아니라 라이브러리 API를 C ++에서 "C 호환 가능"( " extern "C") 으로"번역 "하기 위해 추가 노력을 기울여야합니다 .

포인트가 이유입니다 수있는 C 라이브러리를 구현하기위한 더 나은 선택이라고 할. 개인적으로 저는 C ++의 이점이 여전히 extern "C"API에 필요한 노력보다 중요하다고 생각 하지만 그것은 저뿐입니다.


Windows는 .NET을 기반으로하고 있으며 Android는 Java를 기반으로하고 ( 일부 API 의 구현 세부 사항은 C ) iOS / OSX는 Objective-C를 기반으로합니다.
user253751

1
프로그래밍 세계에서 영어는 이미 지배적 인 언어입니다. 다른 직업보다 지배적입니다.
Siyuan Ren

3
@immibis : Windows, Linux / Android 및 BSD / OSX는 모두 C로 작성된 인터페이스이며 C로 작성된 인터페이스와 함께 C로 작성된 커널입니다. 그 위에 무엇이 내장되어 있든 Java에는 JNI가 필요합니다. Perl에는 C 호출이 필요합니다. NET에는 C 호출이 필요하고 Python에는 C 호출이 필요하며 Objective-C에는 C 호출이 필요합니다. 그중 어느 것도 C ++ 호출 이 필요 하지 않습니다.
DevSolar

@DevSolar 많은 안드로이드의 것들이 기본적으로 자바로 작성되었으며 JNI를 사용하지 않습니다 ( "뒤로"를 사용하여 C에서 Java 코드를 호출 할 수는 있지만 기본적으로 Java임을 확인합니다). iOS / OSX에 대한 경험은 없지만 Objective-C와 동일하다고 들었습니다.
user253751

3
@immibis : 그러나 당신 OS 커널과 그 사용자 공간의 차이점을 알고 있습니까? 나는 대부분 Java 사용자 공간이 안드로이드가 내 데스크탑에서 실행되는 Linux 커널보다 C 스타일 시스템 호출을 가진 Linux 커널보다 덜하게 만든다는 것을 심각하게 의심합니다. 또한 커널이나 미들웨어에서 Java를 사용하고 있는지 의심됩니다. 실제로, 나는 그들이 C를 사용하고 있다는 것을 알고 있습니다. 이것은 다른 방식으로 암탉과 관련된 문제입니다. 이전에 C에서 수행되었으므로 여전히 C에서 수행하는 것이 훨씬 쉽습니다 .
DevSolar

6

다른 답변이 이미 제공 한 세부 정보를 남기십시오.

많은 언어가 C 바인딩을 제공하는 이유는 모든 * nix 및 Windows 운영 체제가 C 인터페이스를 통해 대부분의 OS API를 노출하기 때문입니다. 따라서 언어 구현은 이미 주요 Oses에서 실행될 수 있도록 C와 인터페이스해야합니다. 따라서 언어 자체에서 C 인터페이스와 직접 통신하는 것도 간단합니다.


5

이유가 없습니다. 표현하려는 의미가 기본적으로 C와 호환되고 템플릿과 같은 것이 아니라면 구현이 C로 작성된 경우 더 쉽게 바인딩 할 수있는 이유가 없습니다. 사실상 C 인터페이스가 될 수 있다는 것은 정의의한 것입니다. 다른 언어로 된 구현을 포함하여 이진 계약을 충족시킬 수있는 모든 구현으로 채워집니다. 이러한 방식으로 작동 할 수있는 C 이진 계약을 구현할 수있는 C ++ 이외의 언어가 있습니다.

실제로 의미있는 것은 실제로 유용한 시맨틱 스나 공룡 시대에 머무를 이유를 선택하기 위해 필사적으로 노력하는 새로운 언어 나 아이디어를 배우기를 원하지 않는 사람들입니다.


4
나는 당신이 맞다고 생각하고 downvoters는 질문을 오해했지만 실제로 당신의 대답은 잠재적 인 오해를 강조하기 위해 그리워합니다. "전적으로 C로 작성된 라이브러리"대 "C ++로 작성된 C 인터페이스가있는 라이브러리"
Doc Brown

@ Snowman : C ++ 바인딩 문제가있는 것은 C 바인딩 노출 문제와 전혀 관련이 없습니다.
DeadMG

2
유용한 의미와 기능을 가진 언어를 선택한 다음 C 인터페이스로 번역하도록 강요 하시겠습니까? 클래스와 템플릿은 피할 수 있지만 (처음에 C ++를 사용하는 이유에 대해 의문을 제기 할 수는 있지만) C 바인딩을 사용하는 모든 함수는 예외를 C 코드로 이스케이프시키지 않고 예외를 잡아야합니다. C 호환 라이브러리를 사용하는 사람은 이제 인쇄물 C의 ABI 충돌 및 라이브러리 불일치 외에도 C ++ 및 해당 ABI 충돌 및 라이브러리 불일치를 처리해야합니다.
prosfilaes

2
@prosfilaes : 예외를 리턴 코드로 변환하는 것은 쉽지 않습니다. 클래스를 C API로 쉽게 낮출 수 있고 구현에서 템플릿을 사용하지 않아도되므로 클래스 사용을 피할 필요가 없습니다. 또한 사용자는 소스에서 빌드하지 않는 한 C ++ ABI 충돌에 대해 알 필요가 없습니다.이 경우 소스 언어에 관계없이 소스 언어를 처리해야합니다.
DeadMG

4
필자는 C ++에서 C API로 라이브러리를 작성하지 않아야하기 때문에 공룡이 아닌 C를 사용해야하는 이유가 있기 때문에 다운 투표했습니다. 언어 X의 API를 작성하는 경우 C, FORTRAN, COBOL, BLISS 또는 Java이기 때문에 항상 해당 언어로 작성하는 것이 더 간단하고 쉽고 정확하며 더 멋진 시간을 쓰는 시간이 있습니다. , 더 재미있는 언어와 인터페이스.
prosfilaes

2

다른 언어와 인터페이스 할 때 두 가지 주요 축이 있습니다.

  • 인터페이스가 수행 할 수있는 개념 : 단지 가치? 참조? 제네릭?
  • 인터페이스가 "바이너리"(ABI)로 구현되는 방법

C는이 두 가지 측면에서 C ++보다 장점이 있습니다.

  • C는 대부분의 다른 모든 언어로 나타나는 대부분 간단한 개념을 가지고 있습니다 1
  • C 바이너리의 ABI는 OS 2에 의해 결정됩니다.

이제 대부분의 언어가 C와 비슷한 개념을 갖는가는 "단순"또는 "기존"때문일 수 있습니다. 중요한 것은 요점은 그들이하는 것입니다.

반대로 C ++에는 복잡한 개념이 있으며 ABI는 각 컴파일러에 의해 결정됩니다 (많은 사람들이 Windows를 제외하고 Itanimum ABI를 준수하지만 ...). 실제로 Herb Sutter는이 문제를 부분적으로 해결하기 위해 OS별로 C ++ ABI를 수정하도록 제안했습니다. 또한 C ++ FFI가 가능하다는 것을 알아야합니다 .D는 3을 시도하고 있습니다.

1 variadics ( ...)를 제외하고 는 단순하지 않습니다

2 C에는 표준 ABI가 있습니까?

3 D를 레거시 C ++ 코드와 인터페이스


0

기본적으로 ABI 표준화로 귀결됩니다. C 나 C ++에는 다른 언어로 작성된 이진 파일 간 인터페이스에 사용할 수있는 표준화 된 ABI가 없지만 C는 사실상의 표준이되었으며 모든 사람은이를 알고 있으며 다른 모든 사람은 언어와 관련하여 동일하고 간단한 규칙을 사용할 수 있습니다. 타입과 함수 호출.

C ++은 표준 ABI를 가질 수 있지만 Stroustrup은 자신이 필요하지 않다고 말했다. 그는 또한 컴파일러 작성자들로부터 합의를 얻는 것이 어려울 것이라고 말했다 (물론 C ++ 표준위원회는 기존의 것과 비슷한 ABI를 발행하고 컴파일러 작성자는 단순히 바이너리와 호환되지 않는 다음 버전의 컴파일러를 변경하게 될 것이라고 의심한다) 어쨌든 이전 버전의 컴파일러로 빌드되었습니다. 새로운 Sun 컴파일러로 라이브러리를 다시 컴파일하고 이전 컴파일러와 작동하지 않는 것을 발견했습니다)

일부 회사는 표준 ABI를 사용하기로 옮겼으며 Microsoft는 90 년대에 COM 방식으로이 프로세스를 시작했으며 오늘날에는이를 WinRT ABI로 구체화했습니다 (다른 WinRT와 혼동하지 말 것). C #으로 작성된 프로그램이 C 또는 C ++로 작성된 라이브러리와 통신 할 수 있도록하는 테이블 OS 유형) (예 : Microsoft의 자체 OS 계층은 C ++로 작성되고 WinRT를 사용하여 노출되며 OS 런타임 루틴을 호출 할 때 C # 응용 프로그램에서 사용됨)

표준기구가이 상황을 해결하지 않으면 누구나 할 수있는 일이 많지 않습니다. Microsoft는 분명히 그 가치를보고 플랫폼에 맞게이를 해결하기위한 조치를 취했습니다.

따라서 실제로 C 언어 바인딩을 제공 하지 않습니다 . 아무도 듣고 듣지도 않고 일어납니다.


-2

모든 대답은 실제 문제에 미치지 못합니다. C ++ 컴파일은 "이름 맹 글링"을 도입하므로 바이너리는 "단순한"함수 호출과 호환되지 않습니다.

모든 ABI는 표준화하려는 시도에 지나지 않습니다.

일반적으로 일반 C ++을 고수하더라도 다른 컴파일러로 컴파일 된 함수를 교차 링크 할 수는 없습니다. 이전에는 이들이 호환되지 않는다고 확신 했지만 요즘에는 표준화가 시작되고 있습니다.)

OTOH C는 "높은 수준의 어셈블리"로 정확하게 설계되었으며 모든 종류의 쉬운 인터페이스가 가능합니다. 언어 간 선호에 더 적합하다는 것은 놀라운 일이 아닙니다.

참고 사항 : 원래 C ++ 컴파일러 (cfront)는 실제로 "아래에서 어셈블리"를 생성하는 gcc와 같이 컴파일 해야하는 C 소스를 생성했습니다.

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