Recentemente, eu queria saber quando usar C sobre C ++ e vice-versa? Felizmente, alguém já me venceu e, apesar de demorar um pouco, fui capaz de digerir todas as respostas e comentários para essa pergunta.
No entanto, um item nessa postagem continua sendo abordado repetidamente, sem nenhum tipo de exemplo, verificação ou explicação:
"O código C é bom para quando você deseja ter várias ligações de idioma para sua biblioteca"
Isso é uma paráfrase. Devo observar que várias pessoas apontam que várias ligações de linguagem são possíveis em C ++ (através de algum extern
funcionamento), mas, no entanto, se você ler essa publicação na íntegra, é bastante óbvio que C é ideal para portabilidade / ligação de linguagem. Minha pergunta é: por que?
Alguém pode fornecer razões concretas pelas quais escrever bibliotecas em C facilita ligações e / ou portabilidade em outros idiomas?
Respostas:
C possui uma interface muito, muito mais simples, e suas regras para converter uma interface de código-fonte em uma interface binária são simples o suficiente para que a geração de interfaces externas à qual se ligar seja feita de maneira bem estabelecida. O C ++, por outro lado, tem uma interface incrivelmente complicada e as regras para a ligação ABI não são padronizadas, nem formalmente nem na prática. Isso significa que praticamente qualquer compilador de qualquer idioma para qualquer plataforma pode se vincular a uma interface C externa e saber exatamente o que esperar, mas para uma interface C ++, é essencialmente impossível porque as regras mudam dependendo de qual compilador, qual versão e qual plataforma com a qual o código C ++ foi construído.
fonte
extern "C"
, ainda é mais trabalho adicional fazê-lo, que deve ser equilibrado com os recursos fornecidos pelo C ++)extern "C"
.Se você está tentando se comunicar com um falante de outro idioma, o pidgin é mais fácil do que o inglês shakespeariano.
Os conceitos de C - chamadas de função, ponteiros, seqüências terminadas em NULL - são muito diretos, portanto outros idiomas podem implementá-los facilmente o suficiente para chamar funções em C. Por razões históricas, muitos outros idiomas são implementados em C, o que torna as funções de chamada C ainda mais fáceis.
O C ++ adiciona várias classes de coisas, com herança e vtables e modificadores de acesso; exceções, com pilha desenrolando e alterando o fluxo de controle; modelos. Tudo isso torna mais difícil para outros idiomas usar ligações C ++: na melhor das hipóteses, há mais "cola" ou código de interoperabilidade para implementar e, na pior, os conceitos não são traduzidos diretamente (devido a diferenças nos modelos de classe, manipulação de exceção, etc.) Para modelos em particular, o simples uso (instanciação) deles normalmente requer uma etapa de compilação com um compilador C ++, o que complica bastante o uso de outros ambientes.
Com tudo isso dito, é possível exagerar a dificuldade de fornecer ligações de uma biblioteca C ++ para outro idioma:
extern "C"
, então você pode exportar ligações de linguagem no estilo C (com toda a simplicidade e compatibilidade das ligações C) de uma biblioteca C ++ (com a limitação de que você não pode expor nenhuma funcionalidade específica do C ++) .fonte
C é um dos idiomas mais antigos ainda existentes. Sua ABI é simples e praticamente todos os sistemas operacionais ainda em uso atualmente foram escritos nela . Enquanto alguns desses sistemas operacionais podem ter adicionado coisas, por exemplo, em C # /. NET ou qualquer outro item no topo, lá embaixo, eles estão muito mergulhados em C.
Isso significa que, para usar a funcionalidade fornecida pelo sistema operacional, praticamente todas as linguagens de programação existentes precisam de uma maneira de interagir com as bibliotecas C de qualquer maneira . Perl, Java, C ++, todos eles fornecem formas nativas de "falar C", porque precisavam se não quisessem reinventar todas as rodas existentes.
Isso faz do C o latim das linguagens de programação. (Quantos anos de internet antes dessa metáfora deve ser "o inglês das línguas de programação"?)
Ao escrever sua biblioteca em C, você obtém uma interface compatível com C de graça (obviamente). Se você estiver escrevendo sua biblioteca em C ++, poderá obter ligações C, por meio de
extern "C"
declarações mencionadas.No entanto , você pode obter essas ligações única para a funcionalidade que pode ser expresso em C .
Portanto, a API da sua biblioteca não pode usar ...
Um exemplo simples, você precisaria para fazer suas funções exportadas tomar e retornar matrizes (
[]
) em vez destd::vector
(oustd::string
para que o assunto).Portanto, você não apenas não seria capaz de fornecer as coisas boas que o C ++ tem a oferecer aos clientes da sua biblioteca, mas também teria que fazer um esforço adicional para "traduzir" a API da sua biblioteca de C ++ para "compatível com C" (
extern "C"
).Por isso, pode- se afirmar que C é a melhor escolha para implementar uma biblioteca. Pessoalmente, acho que os benefícios do C ++ ainda superam o esforço necessário para uma
extern "C"
API, mas sou apenas eu.fonte
Deixando de fora os detalhes, outras respostas já fornecem:
A razão pela qual tantas linguagens fornece uma ligação C é que todos os sistemas operacionais * nix e Windows expõem a maior parte de sua API do sistema operacional por meio de uma interface C. Portanto, a implementação da linguagem já precisa interagir com C para poder rodar nos principais Oses. Portanto, é simples também oferecer comunicação direta com qualquer interface C a partir do próprio idioma.
fonte
Não há razão. Se a semântica que você está tentando expressar é fundamentalmente compatível com C e não se parece com modelos, não há razão para você se ligar mais facilmente se a implementação for escrita em C. Na verdade, é basicamente por definição que uma interface C pode ser preenchido por qualquer implementação que possa atender ao contrato binário, incluindo uma implementação em outro idioma. Existem outras linguagens além do C ++ que podem implementar contratos binários em C que podem funcionar dessa maneira.
O que realmente se resume a pessoas que não querem aprender novos idiomas ou idéias que tenham semântica ou recursos realmente úteis, tentando desesperadamente escolher qualquer motivo para permanecer na era dos dinossauros.
fonte
Existem dois eixos principais ao fazer interface com outro idioma:
C tem uma vantagem sobre C ++ nessas duas frentes:
Agora, por que a maioria das linguagens tem um conjunto de conceitos semelhante ao de C pode ser devido a ser "simples" ou "pré-existente"; não importa, porém, o ponto é que eles fazem.
Pelo contrário, o C ++ possui conceitos complexos e a ABI é decidida por cada compilador (embora muitos aderam à Itanimum ABI, exceto no Windows ...). Na verdade, houve uma proposta de Herb Sutter para que os sistemas operacionais corrigissem uma ABI C ++ (por sistema operacional) para resolver parcialmente esse problema. Além disso, deve-se observar que um CFI FFI é possível, D está tentando-o 3 .
1 Exceto variadics (
...
), esses não são simples2 C possui uma ABI padrão?
3 Interface de código D para C ++ herdado
fonte
Fundamentalmente, tudo se resume à padronização da ABI. Embora nem C nem C ++ tenham uma ABI padronizada que outras linguagens possam usar para fazer a interface entre binários escritos, C se tornou um padrão de fato, todo mundo sabe disso e todo mundo pode usar as mesmas regras simples que a linguagem possui com relação a tipos e chamadas de função.
O C ++ poderia ter uma ABI padrão, mas Stroustrup disse que não vê a necessidade de uma. Ele também diz que seria difícil obter consenso dos escritores de compiladores (embora eu duvide que - o comitê padrão C ++ emitisse uma ABI semelhante às existentes e os escritores de compiladores simplesmente alterariam a próxima versão de seus compiladores, que ocasionalmente são incompatíveis com binários de qualquer maneira, construído com versões antigas de seus compiladores - lembro-me de recompilar algumas bibliotecas com um novo compilador Sun e descobrir que elas não funcionaram com as antigas)
Você notará que algumas empresas passaram a usar uma ABI padrão, a Microsoft iniciou esse processo com o COM nos anos 90, e hoje elas refinaram isso na ABI do WinRT (não confunda com o outro WinRT que se refere para um tipo de tabela OS) que permite que programas escritos em C # se comuniquem com bibliotecas escritas em C ou C ++ (ou seja, a camada de SO da Microsoft é escrita em C ++, exposta usando o WinRT e consumida por aplicativos C # quando chamam qualquer rotina de tempo de execução do SO)
Não há muito o que alguém possa fazer, a menos que um órgão de padrões acelere e corrija essa situação. A Microsoft obviamente vê o valor e tomou medidas para resolvê-lo em sua plataforma.
Portanto, a resposta é realmente C não fornece ligações de idioma. Acontece que ninguém os ouviu e os consome independentemente.
fonte
Todas as respostas ficam aquém do problema real: a compilação do C ++ apresenta "name mangling", portanto os binários são incompatíveis com as chamadas de função "simples".
Todo o material da ABI é pouco mais que uma tentativa de padronizá-lo.
Em geral, não é garantido que você possa vincular funções compiladas com diferentes compiladores, mesmo se você seguir o C ++ simples. Antigamente, era certo que eles eram incompatíveis, mas hoje em dia a padronização está se aproximando;)
O OTOH C foi projetado precisamente para ser um "conjunto de alto nível" e permitir todo tipo de interface fácil. Não deve surpreender que seja mais adequado ao gosto entre idiomas.
Nota lateral: o compilador C ++ original (cfront) realmente produziu a fonte C que precisava ser compilada, exatamente como o gcc que produz o Assembly "under the hood".
fonte