| 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 |
|
|
|
| [ 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. |
|
|
|
| [ 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. |
|
|
|
| [ 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. |
|
|
|
| [ 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
}
|
|
|
| [ 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. |
|
|
|
| [ 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. |
|
|
|
| [ 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. |
|
|
|
| [ 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. |
|
|
|
| [ 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. |
|
|
|