C ++에는 많은 이식성 문제가 있는데, 이는 바이너리 수준에서의 표준화가 없기 때문입니다.
나는 그것이 그렇게 간단하다고 생각하지 않습니다. 제공된 답변은 이미 표준화에 중점을 두지 않은 것에 대한 훌륭한 근거를 제공하지만 C ++은 ABI 표준으로서 C와 진정으로 경쟁하기에 너무 언어가 풍부 할 수 있습니다 .
함수 오버로딩, vtable 비 호환성, 예외가있는 비 호환성 등으로 인해 이름이 바뀌면서 모듈 경계를 넘을 수 있습니다.이 모두가 정말 고통스럽고 적어도 vtable 레이아웃을 표준화 할 수 있기를 바랍니다.
그러나 ABI 표준은 단지 하나의 컴파일러에서 생성 된 C ++ dylib를 다른 컴파일러가 빌드 한 다른 바이너리에서 사용할 수 있도록 만드는 것이 아닙니다. ABI가 사용됩니다 언어 간 됩니다 . 적어도 첫 번째 부분을 다룰 수 있다면 좋을 것입니다.하지만 C ++이 보편적 인 ABI 수준에서 C와 경쟁하는 것을 볼 수있는 방법은 없습니다. 가장 광범위하게 호환되는 dylib를 만드는 데 중요합니다.
다음과 같이 내 보낸 간단한 함수 쌍을 상상해보십시오.
void f(Foo foo);
void f(Bar bar, int val);
... 그리고 상상 Foo
과 Bar
매개 변수화 된 생성자와 클래스했다, 생성자, 이동 생성자, 비 사소한 소멸자를 복사합니다.
그런 다음 Python / Lua / C # / Java / Haskell / etc 시나리오를 사용하십시오. 개발자가이 모듈을 가져 와서 해당 언어로 사용하려고합니다.
먼저 함수 오버로딩을 사용하여 심볼을 내보내는 방법에 대한 이름 관리 표준이 필요합니다. 이것은 더 쉬운 부분입니다. 그러나 실제로 "mangling"이라는 이름이되어서는 안됩니다. dylib 사용자는 이름을 기준으로 기호를 찾아야하므로 여기에 과부하가 발생하면 이름이 완전히 엉망처럼 보이지 않아야합니다. 어쩌면 기호 이름이 "f_Foo"
"f_Bar_int"
그런 종류 일 수도 있습니다 . 개발자가 실제로 정의한 이름과 충돌 할 수 없도록해야합니다. 아마도 ABI 사용을 위해 일부 기호 / 문자 / 수집을 예약했을 것입니다.
그러나 지금은 더 힘든 시나리오입니다. 예를 들어 Python 개발자는 이동 생성자, 복사 생성자 및 소멸자를 어떻게 호출합니까? 아마도 우리는 dylib의 일부로 그것들을 내보낼 수 있습니다. 하지만 경우 Foo
와Bar
다른 모듈에 수출하고 있습니다? 이 dylib와 관련된 기호와 구현을 복제해야합니까? 여러 가지 dylib 인터페이스에 얽혀서 여기에 객체를 만들고 여기에 복사하고, 여기에 복사하고, 여기에서 파괴해야하기 때문에 정말 성가 시게 될 수 있기 때문에 제안합니다. 동일한 기본 관심사가 C에 다소 적용될 수 있지만 (보다 수동 / 명시 적으로) C는 사람들이 프로그래밍하는 방식에 따라이를 피하는 경향이 있습니다.
이것은 어색함의 작은 샘플 일뿐입니다. f
위 의 함수 중 하나가 BazException
JavaScript에 생성자 및 소멸자를 포함하고 std :: exception을 파생시키는 C ++ 클래스를 throw 하면 어떻게됩니까 ?
기껏해야 하나의 C ++ 컴파일러가 생성 한 바이너리에서 다른 바이너리가 생성하는 다른 바이너리로 작동하는 ABI 만 표준화 할 수 있다고 생각합니다. 물론 그것은 좋을 것이지만, 나는 이것을 지적하고 싶었습니다. 일반적으로 크로스 컴파일러에서 작동하는 일반화 된 라이브러리를 배포하기 위해 이러한 우려가 수반되는 경우가 많으며이를 실제로 일반화하고 호환되는 크로스 언어로 만들고자하는 경우가 많습니다.
제안 된 해결책
COM 스타일 인터페이스로 API / ABI에 C ++ 인터페이스를 사용하는 방법을 찾기 위해 고군분투 한 후에 제안한 솔루션은 "C / C ++"(pun) 개발자가되는 것입니다.
C를 사용하여 구현을 위해 C ++로 범용 ABI를 작성하십시오. 우리는 내보내기 함수와 같은 작업을 수행하여 힙에서 이러한 객체를 생성하고 파괴하는 명시 적 함수로 불투명 한 C ++ 클래스에 대한 포인터를 반환 할 수 있습니다. 구현에 C ++을 완전히 사용하더라도 ABI 관점에서 C 미학을 사랑하십시오. 함수 포인터 테이블을 사용하여 추상 인터페이스를 모델링 할 수 있습니다. 이 내용을 C API로 마무리하는 것은 지루하지만, 그와 함께 제공되는 배포의 이점과 호환성은 매우 가치가 있습니다.
그런 다음이 인터페이스를 너무 직접 사용하는 것을 좋아하지 않는다면 (적어도 RAII 이유로는 안 됨) SDK와 함께 제공되는 정적으로 연결된 C ++ 라이브러리에 원하는 모든 것을 랩핑 할 수 있습니다. C ++ 클라이언트가이를 사용할 수 있습니다.
파이썬 클라이언트는이 피 토닉을 만들 방법이 없기 때문에 C 또는 C ++ 인터페이스를 직접 사용하고 싶지 않습니다. 그들은 그것을 자체의 pythonique 인터페이스로 마무리하고 싶기 때문에 실제로 가능한 한 쉽게 만들기 위해 최소한의 C API / ABI를 내보내는 것이 좋습니다.
COM 스타일 인터페이스 등을 완고하게 제공하려는 것보다 많은 C ++ 산업이 더 많은 이점을 얻을 수 있다고 생각합니다. 또한이 딜 리브 사용자가 어색한 ABI에 대해 걱정할 필요가 없기 때문에 우리의 모든 삶을 더 쉽게 만들 것입니다. C는 간단하고 ABI 관점에서 간단하기 때문에 모든 종류의 FFI에 대해 자연스럽고 최소한으로 작동하는 API / ABI를 만들 수 있습니다.