it-roy-ru.com

Почему C предоставляет языковые «привязки», где C ++ терпит неудачу?

Мне недавно было интересно когда использовать C над C++, и наоборот? К счастью, кто-то уже победил меня и хотя это Потребовалось время, я смог переварить все ответы и комментарии на этот вопрос.

Однако, один пункт в этом посте продолжает рассматриваться снова и снова, без какого-либо примера, проверки или объяснения:

"Код на C подходит для случаев, когда вы хотите иметь несколько языковых привязок для вашей библиотеки"

Это парафраз. Я должен отметить, что несколько человек отмечают, что в C++ возможны множественные языковые привязки (через некоторое extern функционирование), но, тем не менее, если вы прочитаете этот пост целиком, вполне очевидно, что C идеально подходит для переносимости/языковая привязка. Мой вопрос: почему?

Может ли кто-нибудь указать конкретные причины, по которым написание библиотек на C упрощает привязку и/или переносимость на другие языки?

60
smeeb

C имеет гораздо более простой интерфейс, и его правила для преобразования интерфейса с исходным кодом в двоичный интерфейс достаточно просты, поэтому генерация внешних интерфейсов для привязки выполняется хорошо известным способом. С ++, с другой стороны, имеет невероятно сложный интерфейс, и правила для привязки ABI вообще не стандартизированы ни формально, ни на практике. Это означает, что практически любой компилятор для любого языка для любой платформы может связываться с внешним интерфейсом C и точно знать, чего ожидать, но для интерфейса C++ это практически невозможно, поскольку правила меняются в зависимости от того, какой компилятор, какая версия и какая платформа, на которой был построен код C++.

В C также нет стандартных правил реализации двоичного языка, но это на порядок проще, и на практике компиляторы используют те же правила. Другой причиной, затрудняющей отладку кода C++, является упомянутая выше сложная грамматика, поскольку отладчики часто не могут иметь дело со многими языковыми функциями (размещать точки останова в шаблонах, команды разбора указателей в окнах отображения данных и т.д.).

Отсутствие стандартного ABI (бинарный интерфейс приложения) имеет еще одно следствие - делает доставку интерфейсов C++ другим группам/клиентам нецелесообразно, поскольку пользовательский код не будет работать, если он не скомпилирован с теми же инструментами и опциями сборки. Мы уже видели другой источник этой проблемы - нестабильность бинарных интерфейсов из-за отсутствия инкапсуляции времени компиляции.

- Дефектный C++

69
Mason Wheeler

Если вы пытаетесь общаться с носителем другого языка, Pidgin проще, чем шекспировский английский.

Концепции C - вызовы функций, указатели, строки, оканчивающиеся NULL - очень просты, поэтому другие языки могут легко реализовать их достаточно хорошо, чтобы вызывать функции C. По историческим причинам многие другие языки реализованы в C, что делает вызов функций C еще проще.

C++ добавляет довольно много вещей - классов, с наследованием и vtables и модификаторами доступа; исключения, с разматыванием стека и изменением потока управления; шаблоны. Все это затрудняет использование привязок C++ для других языков: в лучшем случае для реализации имеется больше "связующего" кода или кода взаимодействия, а в худшем случае концепции не переводятся напрямую (из-за различий в моделях классов, обработки исключений, так далее.). В частности, для шаблонов простое использование (создание экземпляров) их обычно требует этапа компиляции с компилятором C++, что значительно значительно усложняет их использование в других средах.

С учетом всего сказанного можно преувеличить сложность предоставления привязок из библиотеки C++ к другому языку:

  • Привязки C++ могут быть такими же совместимыми, как C, если вы готовы работать над этим. Как указывает @DeadMG, C++ поддерживает extern "C", так что вы можете экспортировать привязки языка C-стиля (со всей простотой и совместимостью привязок C) из библиотеки C++ (с тем ограничением, что вы не можете предоставлять какую-либо специфическую для C++ функциональность).
  • Другим распространенным возражением против привязок языка C++ является отсутствие стабильности ABI для C++, но это также завышено; C++ ABI менее стандартизированы, чем C ABI, но стандарты и стандарты де-факто существуют (Itanium C++ ABI, который также используется в OS X ; стандарт де-факто GCC для Linux). Windows хуже, но даже в Windows пребывание в пределах одной версии Visual C++ должно работать нормально.
32
Josh Kelley

Си является одним из старейших языков, которые все еще существуют. Его ABI прост, , и практически все операционные системы, которые используются сегодня, написаны на нем . Хотя некоторые из этих ОС, возможно, добавили вещи, например, в C #/.NET или что-то сверху, внизу они очень погружены в C.

Это означает, что для того, чтобы использовать функциональность, предоставляемую ОС, практически каждому языку программирования необходим способ взаимодействия с библиотеками C в любом случае . Perl, Java, C++, они все изначально предоставляют способы "говорить на C", потому что им нужно было, если они не хотели изобретать каждое колесо Там есть.

Это делает C латиницей языков программирования. (Сколько лет интернета до этой метафоры должно быть "английским языком программирования"?)


Когда вы пишете свою библиотеку на C, вы получаете C-совместимый интерфейс бесплатно (очевидно). Если вы пишете свою библиотеку на C++, вы можете получить привязки C через extern "C" декларации, как вы упомянули.

Однако, вы можете получить эти привязки только для функциональности , которая может быть выражена в C .

Таким образом, ваш библиотечный API не может использовать ...

  • шаблоны,
  • классы,
  • исключения,
  • любые функции , принимающие или возвращающие объекты.

Один простой пример, вам нужно заставить ваши экспортированные функции брать и возвращать массивы ([]) вместо std::vector (или std::string в этом отношении).

Таким образом, вы не только не сможете предоставить что-то хорошее, что C++ может предложить клиентам вашей библиотеки, но и вам придется перейти на дополнительные попытка "перевести" API вашей библиотеки с C++ на "C-совместимый" (extern "C").

Вот почему можно сделать вывод, что C - лучший выбор для реализации библиотеки. Лично я думаю, что преимущества C++ все еще перевешивают необходимые усилия для extern "C" API, но это только я.

21
DevSolar

Оставляя детали, другие ответы уже дают:

Причина, по которой многие языки предоставляют привязку C, заключается в том, что все операционные системы * nix и Windows предоставляют большую часть своего API-интерфейса ОС через интерфейс C. Таким образом, языковая реализация уже должна взаимодействовать с C, чтобы иметь возможность работать на основных Oses. Следовательно, также просто предложить непосредственное взаимодействие с любым C-интерфейсом из самого языка.

6
Martin Ba

Нет причин. Если семантика, которую вы пытаетесь выразить, в основном C-совместима, а не что-то вроде шаблонов, нет никаких причин, по которым вы можете связать проще, если реализация написана на C. На самом деле, это в значительной степени по определению = что интерфейс C может быть заполнен любой реализацией, которая может соответствовать бинарному контракту, включая реализацию на другом языке. Существуют языки, отличные от C++, которые могут реализовывать двоичные контракты C, которые могут работать таким образом.

То, к чему это действительно сводится, - это люди, которые не хотят изучать новые языки или идеи, которые имеют действительно полезную семантику или функции, отчаянно пытающиеся найти любую причину, чтобы остаться в эпоху динозавров.

5
DeadMG

При взаимодействии с другим языком существует две основные оси:

  • концепции, которые может перенести интерфейс: просто значения? Ссылки? дженерики?
  • как интерфейс реализован в "бинарных файлах" (называемых ABI)

C имеет преимущество перед C++ по этим двум направлениям:

  • C имеет в основном простые понятия, которые встречаются в большинстве других языков.1
  • ABI C двоичных файлов определяется ОС2

Теперь почему большинство языков имеют сходный набор понятий, чем C, возможно, из-за того, что он "простой" или "уже существующий"; это не имеет значения, дело в том, что они делают.

Напротив, C++ имеет сложные концепции, и ABI определяется каждым компилятором (хотя многие придерживаются Itanimum ABI, за исключением Windows ...). На самом деле было предложение Херба Саттера, чтобы ОС исправляли ABI C++ (для каждой ОС), чтобы частично решить эту проблему. Кроме того, следует отметить, что FFI C++ возможен, D пытается это3,.

1 За исключением вариадик (...), это не просто

2 у C есть стандартный ABI?

3 Взаимодействие D с устаревшим кодом C++

2
Matthieu M.

В основном это сводится к стандартизации ABI. Хотя ни C, ни C++ не имеют стандартизированного ABI, который другие языки могут использовать для взаимодействия между написанными двоичными файлами, C стал стандартом де-факто, все это знают, и все остальные могут использовать те же простые правила, которые есть у языка в отношении типы и вызовы функций.

C++ может иметь стандартный ABI, но Страуструп сказал, что он не видит необходимости в этом. Он также говорит, что было бы трудно получить консенсус от авторов компиляторов (хотя я сомневаюсь, что - стандартный комитет C++ выпустит ABI, аналогичный существующим, а разработчики компиляторов просто изменят следующую версию своих компиляторов, которые иногда несовместимы с двоичными файлами В любом случае, я собрал пару библиотек с новым компилятором Sun и обнаружил, что они не работают со старыми).

Вы заметите, что некоторые компании перешли на использование стандартного ABI, Microsoft начала этот процесс с COM еще в 90-х годах, и сегодня они усовершенствовали его в WinRT ABI (не путать с другим WinRT, который относится к к типу табличной ОС), который позволяет программам, написанным на C #, взаимодействовать с библиотеками, написанными на C или C++ (т. е. собственный уровень ОС Microsoft написан на C++, предоставляется с помощью WinRT и используется приложениями C # при вызове любой подпрограммы выполнения ОС)

Никто не может сделать что-либо, если не подойдет стандартизация и не исправит эту ситуацию. Microsoft, очевидно, видит в этом ценность и предприняла шаги по ее решению для своей платформы.

Таким образом, ответ на самом деле C не обеспечить языковые привязки. Бывает, что никто их не слушал и не потребляет.

0
gbjbaanb