FAQ Lite
Como Fundir C e C++

[ 29.1 ] O que eu preciso saber quando estou misturando códigos C e C++?
[ 29.2 ] Como eu incluo um arquivo-header padrão C em meu código C++?
[ 29.3 ] Como eu posso incluir um arquivo-header de usuário em C no meu código C++?
[ 29.4 ] Como eu posso modificar meus próprios arquivos-header em C, para que seja mais fácil inseri-los (#include) em código C++?
[ 29.5 ] Como eu posso chamar uma função de usuário em C f(int,char,float) a partir de meu código C++?
[ 29.6 ] Como eu posso criar uma função C++ f(int,char,float) que possa ser chamada a partir de meu código C?
[ 29.7 ] Porque o linker está dando erro para funções C/C++ chamadas a partir de funções C++/C?
[ 29.8 ] Como eu passo um objeto de uma class C++ para/de uma função C?
[ 29.9 ] Minha função C pode acessar diretamente dados em um objeto de uma class C++?
[ 29.10 ] Porque eu me sinto distante da máquina em C++, ao contrário do que me sinto em C?

[ 29.1 ] O que eu preciso saber quando estou misturando códigos C e C++?

Há vários pontos que você precisa verificar:
  • Você precisa usar o seu compilador C++ para compilar main() (por exemplo, para inicialização estática)
  • O seu compilador C++ deve dirigir o processo de linking (por exemplo, para que possa resgatar suas próprias bibliotecas)
  • Provavelmente você precise usar compiladores C e C++ adquiridos do mesmo fornecedor, e devem ser de versões compatíveis (por exemplo, devem usar a mesma convenção de chamadas a funções)

Mais ainda, você vai precisar ler o restante desta seção para descobrir como chamar suas funções em C a partir de código C++, e como chamar funções em C++ a partir de código em C

Topo
[ 29.2 ] Como eu incluo um arquivo-header padrão C em meu código C++?

Para #include um arquivo-header padrão - tal como <stdio.h> - você não precisa fazer nada fora do comum. Por exemplo:
    // This is C++ code
    
    #include <stdio.h>          // Note: nothing unusual in #include line
    
    main()
    {
      printf("Hello world\n");  // Note: nothing unusual in the call
    } 
Nota: Há diferentes orientações aplicáveis a arquivos-header C. Há dois casos: um em que você não pode modificar o arquivo-header, e um outro em você pode.
Topo
[ 29.3 ] Como eu posso incluir um arquivo-header de usuário em C no meu código C++?

Se você está incluindo um arquivo-header que não foi fornecido pelo sistema, você pode precisar embutir a linha #include em uma construção extern C { /*...*/ }. Isso indica ao compilador que as funções declaradas no arquivo-header são funções em C.
    // This is C++ code
    
    extern "C" {
      // Get declaration for f(int i, char c, float x)
      #include "my-C-code.h"
    }
    
    main()
    {
      f(7, 'x', 3.14);   // Note: nothing unusual in the call
    } 
Nota: Há diferentes orientações aplicáveis a arquivos-header fornecidos pelo sistema (como <stdio.h>) e a arquivos-header que você pode modificar.
Topo
[ 29.4 ] Como eu posso modificar meus próprios arquivos-header em C para que seja mais fácil inserí-los (#include) em código C++?

Se você está incluindo um arquivo-header que não foi fornecido pelo sistema, e se você está habilitado a alterá-lo, você deve considerar fortemente a alternativa de adicionar a lógica extern C{...} dentro do arquivo-header para tornar mais fácil sua inserção em código C++, inclusive por outros usuários C++. Já que o compilador C não entende a construção extern C, você deve embutir o extern C { ... } em um comando #ifdef, para ocultar essa construção do compilador C normal.

Passo 1 - Coloque as seguintes linhas no topo, antes da primeira linha, de seu arquivo-header.

Nota: _cplusplus é #defined se e somente se o compilador é um compilador C++:

    #ifdef __cplusplus
    extern "C" {
    #endif 
Passo 2: Coloque as seguintes linhas após a última linha de seu arquivo-header em C:
    #ifdef __cplusplus
    }
    #endif 
Agora você pode #include seu arquivo-header em C sem extern C em seu código C++:
    // This is C++ code
    
    // Get declaration for f(int i, char c, float x)
    #include "my-C-code.h"   // Note: nothing unusual in #include line
    
    main()
    {
      f(7, 'x', 3.14);       // Note: nothing unusual in the call
    } 
Nota: Há diferentes orientações aplicáveis a arquivos-header fornecidos pelo sistema (como <stdio.h>) e a arquivos-header que você não pode modificar.
Topo
[ 29.5 ] Como eu posso chamar uma função de usuário em C f(int,char,float) a partir de meu código C++?

Se você tem uma função individual em C que você quer chamar, e por qualquer razão você não pode ou não quer #include um arquivo-header no qual a função esteja declarada, você pode declarar a função individual C em seu código C, usando a sintaxe extern C. Naturalmente você precisa usar o protótipo de função completo:
    extern "C" void f(int i, char c, float x); 
Várias funções C podem ser agrupadas entre chaves:
    extern "C" {
      void   f(int i, char c, float x);
      int    g(char* s, const char* s2);
      double sqrtOfSumOfSquares(double a, double b);
    } 
Após isso, você pode simplesmente chamar a função, exatamente como faria se essa fosse uma função C++:
    main()
    {
      f(7, 'x', 3.14);   // Note: nothing unusual in the call
    } 
Topo
[ 29.6 ] Como eu posso criar uma função C++ f(int,char,float) que possa ser chamada a partir de meu código C?

O compilador C++ precisa saber que f(int,char,float) será chamada por um compilador C. Você indica isso através da construção extern C:
    // This is C++ code
    
    // Declare f(int,char,float) using extern C:
    extern "C" void f(int i, char c, float x);
    
    // ...
    
    // Define f(int,char,float) in some C++ module:
    void f(int i, char c, float x)
    {
      // ...
    } 
A linha extern C indica ao compilador que a informação externa enviada ao linker,deve usar uma convenção de chamada e name mangling padrão C (por exemplo, precedida por um caracter underscore). Uma vez que a sobrecarga de nomes não é suportada pelo C, você não pode fazer várias sobrecargas de função que possam ser chamadas simultaneamente por um programa C.
Topo
[ 29.7 ] Porque o linker está dando erro para funções C/C++ chamadas a partir de funções C++/C?

Se você não usou as construções extern C, ou não as usou corretamente, algumas vezes você receberá erros de linker ao invés de erros de compilação. Isso se deve ao fato de que os compiladores C++ normalmente mutilam os nomes de funções (por exemplo, para suportar sobrecarga de função) com critérios diferentes dos usados pelos compiladores C.

Veja na FAQ anterior como usar extern C.

Topo
[ 29.8 ] Como eu passo um objeto de uma class C++ para/de uma função C?

Aqui está um exemplo (para informações sobre extern C, veja as duas FAQs anteriores).
Fred.h: 
    /* This header can be read by both C and C++ compilers */
    #ifndef FRED_H
    #define FRED_H
    
    #ifdef __cplusplus
      class Fred {
      public:
        Fred();
        void wilma(int);
      private:
        int a_;
      };
    #else
      typedef
        struct Fred
          Fred;
    #endif
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    #if defined(__STDC__) || defined(__cplusplus)
      extern void c_function(Fred*);   /* ANSI-C prototypes */
      extern Fred* cplusplus_callback_function(Fred*);
    #else
      extern void c_function();        /* K&R style */
      extern Fred* cplusplus_callback_function();
    #endif
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif /*FRED_H*/ 
Fred.cpp: 
    // This is C++ code
    
    #include "Fred.h"
    
    Fred::Fred() : a_(0) { }
    
    void Fred::wilma(int a) { }
    
    Fred* cplusplus_callback_function(Fred* fred)
    {
      fred->wilma(123);
      return fred;
    } 
main.cpp: 
    // This is C++ code
    
    #include "Fred.h"
    
    int main()
    {
      Fred fred;
      c_function(&fred);
      return 0;
    } 
c-function.c: 
    /* This is C code */
    
    #include "Fred.h"
    
    void c_function(Fred* fred)
    {
      cplusplus_callback_function(fred);
    } 
A passagem de pointers de objetos C++ para/de funções C vai falhar se você passar ou receber de volta qualquer coisa que não seja exatamente o mesmo pointer. Por exemplo, não passe um pointer de classe base e receba de volta um pointer de classe derivada, já que seu compilador C não vai entender as conversões de pointer necessárias para manejar herança múltipla e/ou herança virtual.
Topo
[ 29.9 ] Minha função C pode acessar diretamente dados em um objeto de uma class C++?

Algumas vezes.

Para informações básicas sobre passagem de objetos C++ para/de funções C, leia as FAQs anteriores.

Voce pode acessar, com segurança ,dados de objetos C++ a partir de uma função C se a classe C++:

  • Não tiver nenhuma função virtual, nem mesmo funções virtual herdadas
  • Tiver todos os dados na mesma seção de nível de acesso (private/protected/public)
  • Não tiver subobjetos plenamente contidos que tenham funções virtual

Se a classe C++ tiver qualquer classe base (ou se qualquer dos subobjetos plenamente contidos tiver classe base), o acesso aos dados será tecnicamente não-portável, uma vêz que o leiaute da class sob herança é imposto pela linguagem. Embora na prática, todos os compiladores C++ resolvam isso da mesma maneira: os objetos da classe base aparecem em primeiro lugar (ordenados da esquerda para a direita no caso de herança múltipla), e são seguidos pelos objetos membro.

Mais ainda, se a classe (ou qualquer classe base) contiver qualquer função virtual, quase todos os compiladores C++ colocam um void* dentro do objeto, seja na localização da primeira função virtual, ou no topo do objeto. Mais uma vêz, isso não é requerido pela linguagem, mas é o modo como todos fazem.

Topo
[ 29.10 ] Porque eu me sinto distante da máquina em C++, ao contrário do que me sinto em C?

Porque você está de fato mais distante da máquina de fato.

Como linguagem de programação OO, C++ permite que você modele o problema em seu próprio domínio, o que lhe possibilita programar na linguagem do domínio do problema, ao invés de na linguagem do domínio da solução do problema.

Uma dos pontos fortes do C é o fato de não ter mecanismos ocultos: o que você vê é o que você tem. Você pode ler um programa C e ver cada ciclo de relógio. Esse não é o caso em C++; antigos programadores C (como alguns de nós já foi uma vêz) são ambíguos (talvez hostis) em relação a isso. De qualquer modo, após fazer a transição para o enfoque OO, eles normalmente percebem que embora C++ oculte do programador alguns mecanismos, também fornece um nível de abstração e economia expressiva, que diminuem custos de manutenção sem destruir a performance em tempo de execução.

Naturalmente você pode escrever código ruim em qualquer linguagem; C++ não garante nenhum nível específico de qualidade, reusabilidade, abstração, etc.

C++ não tenta impossibilitar que maus programadores escrevam programas ruins, mas torna possível que desenvolvedores medianos criem software de alto nível.

Topo Anterior Próximo Índice
C++ FAQ Lite
Copyright © 1991-98 by Marshall Cline Ph.D., cline@parashift.com
Tradução: Dagoberto Haele Arnaut

| Home | Bookmarks | Universidades | Para Saber mais | Universidades | WEB Directory | Mapa do site |