Недавно я задавался вопросом, когда использовать C над C ++, и наоборот? К счастью, кто-то уже опередил меня, и хотя мне потребовалось некоторое время, я смог переварить все ответы и комментарии на этот вопрос.
Однако, один пункт в этом посте продолжает рассматриваться снова и снова, без какого-либо примера, проверки или объяснения:
«C-код подходит для случаев, когда вы хотите иметь несколько языковых привязок для вашей библиотеки»
Это парафраз. Я должен отметить, что некоторые люди отмечают, что в C ++ возможны множественные языковые привязки (через некоторое extern
функционирование), но, тем не менее, если вы прочитаете этот пост целиком, вполне очевидно, что C идеален для переносимости / связывания языка. Мой вопрос: почему?
Может ли кто-нибудь предоставить конкретные причины, почему написание библиотек на C позволяет упростить привязки и / или переносимость на другие языки?
Ответы:
C имеет гораздо более простой интерфейс, и его правила для преобразования интерфейса с исходным кодом в двоичный интерфейс достаточно просты, поэтому генерация внешних интерфейсов для привязки выполняется хорошо известным способом. C ++, с другой стороны, имеет невероятно сложный интерфейс, и правила для привязки ABI вообще не стандартизированы ни формально, ни на практике. Это означает, что практически любой компилятор для любого языка для любой платформы может связываться с внешним интерфейсом C и точно знать, чего ожидать, но для интерфейса C ++ это практически невозможно, поскольку правила меняются в зависимости от того, какой компилятор, какая версия и какая платформа, на которой был построен код C ++.
источник
extern "C"
это еще более дополнительная работа, которая должна быть сбалансирована с возможностями, предоставляемыми C ++)extern "C"
.Если вы пытаетесь общаться с носителем другого языка, пиджин проще, чем шекспировский английский.
Концепции C - вызовы функций, указатели, строки, оканчивающиеся NULL - очень просты, поэтому другие языки могут легко реализовать их достаточно хорошо, чтобы вызывать функции C. По историческим причинам многие другие языки реализованы в C, что делает вызов функций C еще проще.
C ++ добавляет довольно много вещей - классов, с наследованием и vtables и модификаторами доступа; исключения, с разматыванием стека и изменением потока управления; шаблоны. Все это затрудняет использование привязок C ++ для других языков: в лучшем случае для реализации имеется больше «связующего» кода или кода взаимодействия, а в худшем случае концепции не переводятся напрямую (из-за различий в моделях классов, обработки исключений, и т.д.). В частности, для шаблонов простое использование (создание экземпляров) их обычно требует этапа компиляции с компилятором C ++, что значительно усложняет их использование в других средах.
С учетом всего вышесказанного можно переоценить сложность предоставления привязок из библиотеки C ++ к другому языку:
extern "C"
, так что вы можете экспортировать привязки языка C-стиля (со всей простотой и совместимостью привязок C) из библиотеки C ++ (с ограничением, что вы не можете предоставлять какую-либо специфическую для C ++ функциональность) ,источник
Си является одним из старейших языков, которые все еще существуют. Его ABI прост, и практически каждая операционная система, все еще используемая сегодня, была написана на нем . В то время как некоторые из этих ОС могут добавлять что-то, например, в C # / .NET или что-то еще сверху, внизу они очень сильно погружены в 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, но это только я.источник
Оставляя детали, другие ответы уже дают:
Причина, по которой многие языки обеспечивают привязку C, заключается в том, что все операционные системы * nix и Windows предоставляют большую часть своего API-интерфейса ОС через интерфейс C. Таким образом, языковая реализация уже должна взаимодействовать с C, чтобы иметь возможность работать на основных Oses. Следовательно, также просто предложить непосредственную связь с любым C-интерфейсом из самого языка.
источник
Нет причины. Если семантика, которую вы пытаетесь выразить, в основном C-совместима, а не что-то вроде шаблонов, нет никаких причин, по которым вы можете связать проще, если реализация написана на C. На самом деле, по определению , интерфейс C может быть заполняется любой реализацией, которая может соответствовать бинарному контракту, включая реализацию на другом языке. Существуют языки, отличные от C ++, которые могут реализовывать двоичные контракты C, которые могут работать таким образом.
То, к чему это действительно сводится, - это люди, которые не хотят изучать новые языки или идеи, которые на самом деле имеют полезную семантику или функции, отчаянно пытаясь найти любую причину, чтобы остаться в эпоху динозавров.
источник
При взаимодействии с другим языком существует две основные оси:
C имеет преимущество перед C ++ по этим двум направлениям:
Теперь, почему большинство языков имеют сходный набор понятий, чем C, может быть из-за того, что он «простой» или «уже существующий»; это не имеет значения, дело в том, что они делают.
Напротив, C ++ имеет сложные концепции, и ABI определяется каждым компилятором (хотя многие придерживаются Itanimum ABI, за исключением Windows ...). На самом деле было предложение Херба Саттера, чтобы ОС исправляли ABI C ++ (для каждой ОС), чтобы частично решить эту проблему. Кроме того, следует отметить, что FFI C ++ возможен, D пытается это сделать 3 .
1 За исключением variadics (
...
), это не просто2 Есть ли у C стандартный ABI?
3 Взаимодействие D с устаревшим кодом C ++
источник
В основном это сводится к стандартизации 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 не обеспечивает языковые привязки. Бывает, что никто их не слушал и не потребляет.
источник
Все ответы не соответствуют реальной проблеме: компиляция C ++ вводит «искажение имен», поэтому двоичные файлы несовместимы с «простыми» вызовами функций.
Все материалы ABI - это не более чем попытка стандартизировать их.
В целом, не гарантируется, что вы можете создавать перекрестные ссылки функций, скомпилированных с помощью различных компиляторов, даже если вы придерживаетесь простого C ++. Раньше он был уверен, что они несовместимы, но в настоящее время набирает силу стандартизация;)
OTOH C был спроектирован именно как «сборка высокого уровня» и обеспечивает всевозможные простые интерфейсы. Это не должно удивлять, это лучше подходит для межъязыковых симпатий.
Примечание: оригинальный компилятор C ++ (cfront) на самом деле создал исходный код C, который должен был быть скомпилирован, точно так же, как gcc, который создает Assembly "под капотом".
источник