2010-05-09 12 views
18

Tal vez no soy la comprensión de las diferencias entre C y C++, sino cuándo y por qué necesitamos utilizarCuándo usar extern "C" en palabras simples?

extern "C" { 

? Aparentemente es una "convención de ligamiento".

Lo leí brevemente y noté que todos los archivos de cabecera .h incluidos con MSVS rodean su código con él. ¿Qué tipo de código es exactamente "código C" y NO "código C++"? Pensé que C++ incluía todo el código C?

Supongo que este no es el caso y que C++ es diferente y que las características/funciones estándar existen en una u otra pero no en ambas (es decir: printf es C y cout es C++), pero que C++ es compatible con versiones anteriores a través de la declaración externa "C". ¿Es esto correcto?

Mi siguiente pregunta depende de la respuesta a la primera, pero la voy a preguntar aquí de todos modos: como los archivos de encabezado MSVS que están escritos en C están rodeados por la "C" externa {...}, ¿cuándo lo harían? ¿Necesitas usar esto tú mismo en tu propio código? Si su código es código C y está tratando de compilarlo en un compilador C++, ¿no debería funcionar sin problemas porque todos los archivos h estándar que incluye ya tendrán la cosa externa "C" en ellos con el compilador C++?

¿Tiene que usar esto al compilar en C++ pero al enlazar a bibliotecas C ya construidas o algo así?

+6

C++ NO es un superconjunto de C. Hay una C válida que no es válida C++. –

+1

@ Theatrus-- ese tipo de afirmación pide un ejemplo. – mmr

+0

theatrus: ¿Pero eso tampoco es siempre el caso? – Russel

Respuesta

0

Las funciones de C++ están sujetas a name mangling. Esto hace que sea imposible llamar directamente desde el código C a menos que se use extern "C".

9

Los compiladores de C++ manipulan los nombres en su tabla de símbolos de forma diferente a los compiladores de C. Debe usar la declaración extern "C" para indicarle al compilador de C++ que use la convención de manipulación de C en su lugar al compilar la tabla de símbolos.

+0

La respuesta es breve y correcta. –

21

Es necesario utilizar extern "C" en C++ cuando se declara una función que se implementó/compilado en C. El uso de extern "C" le dice al compilador/enlazador a utilizar la denominación C y convenciones de llamada, en lugar de la C++ mangling nombre y C++ llamar convenciones que se usarían de otra manera. Para las funciones proporcionadas por otras bibliotecas, casi nunca necesitará usar extern "C", ya que las bibliotecas escritas ya tendrán esto allí para las API públicas que exporta tanto a C como a C++. Sin embargo, si escribe una biblioteca que desea poner a disposición tanto en C como en C++, tendrá que poner eso de manera condicional en sus encabezados.

En cuanto a si todo el código C es código C++ ... no, eso no es correcto. Es un mito popular que C++ es un "superconjunto de C". Mientras C++ ciertamente se esfuerza por ser tan compatible con C como sea posible, hay algunos incompatibilities. Por ejemplo, bool es válido C++ pero no es válido C, mientras que _Bool existe en C99, pero no está disponible en C++.

En cuanto a si alguna vez necesitará usar extern "C" con los archivos ".h" del sistema ... cualquier implementación bien diseñada tendrá esos para usted, para que no necesite usar ellos. Sin embargo, para asegurarse de que se proporcionan, debe incluir el archivo de encabezado equivalente que comienza con "c" y omite ".h". Por ejemplo, si incluye <ctype.h>, casi cualquier sistema razonable tendrá la "C" externa añadida; sin embargo, para asegurarse un encabezado compatible con C++, en su lugar debe incluir el encabezado <cctype>.

Quizás te interese Mixing C and C++ from the C++ FAQ Lite.

+0

Gracias por todas las respuestas. Entonces, ¿solo necesito usar esto cuando incluyo código que ya ha sido compilado en un compilador de C? – Russel

+0

@Russel, sí, suponiendo que lo está incluyendo desde C++, y suponiendo que el encabezado ya no usa extern "C". –

+0

¡Creo que es una buena respuesta! –

2

Utilizo 'extern c' para que C# pueda leer mi código C++ sin tener que descubrir el nombre adicional que se mapea al exportar una función C++ dll. De lo contrario, hay caracteres extra sin sentido (o realmente, no en inglés) que tengo que agregar al final de un punto de entrada de función en el lado C# para acceder correctamente a una función C++ en un dll.

2

extern "C" {} bloques le dicen a un compilador de C++ que use las convenciones de nomenclatura y llamada de C. Si no lo usa, obtendrá errores del enlazador si intenta incluir una biblioteca C con su proyecto C++ porque C++ destruirá los nombres. Yo tiendo a usar esto en todos mis cabeceras C en caso de que se utilizan cada vez en un proyecto de C++:

#ifdef __cplusplus 
extern "C" { 
#endif 

/* My library header */ 

#ifdef __cplusplus 
} // extern 
#endif 
2

Es necesario utilizar extern "C" cuando se quiere utilizar la convención de llamada C en código compilado por un compilador de C++ . Hay dos razones para esto:

  • Tiene una función implementada en C y desea llamarla desde C++.

  • Tiene una función implementada en C++ y desea llamarla desde C. Tenga en cuenta que en este caso solo puede usar la parte C de C++ en la interfaz de función (sin clases, ...).

Aparte de C Esto también se aplica cuando se desea interoperar entre C++ y otros lenguajes que utilizan la misma vocación y convenciones de nombres como C.

Normalmente las declaraciones en un archivo de cabecera C están rodeados de

#ifdef __cplusplus 
extern "C" { 
#endif 

[... C declarations ...] 

#ifdef __cplusplus 
} 
#endif 

para hacerlo utilizable desde C++.

16

Las otras respuestas son correctas, pero un ejemplo completo de "repetición" probablemente ayude. El método canónico para la inclusión de código C en y/proyectos o C++ C es el siguiente:

// 
// C_library.h 
// 

#ifdef __cplusplus 
extern "C" { 
#endif 

// 
// ... prototypes for C_library go here ... 
// 

#ifdef __cplusplus 
} 
#endif 

-

// 
// C_library.c 
// 

#include "C_library.h" 

// 
// ... implementations for C_library go here ... 
// 

-

// 
// C++_code.cpp 
// 

#include "C_library.h" 
#include "C++_code.h" 

// 
// ... C++_code implementation here may call C functions in C_library.c ... 
// 

Nota: el anterior también se aplica a llamar C código de Objective-C++.

+0

Gran ejemplo, gracias. He leído sobre las convenciones de llamada para C++ .. (_cdecl, _stdcall, _fastcall, etc.). ¿Hay una sola convención de llamadas para C? – Russel

+0

@Russel: _cdecl, _stdcall, _fastcall, etc. son abominaciones no estándar de Windows que no se encuentran en el mundo civilizado. ;-) –

+0

Me disculpo :) ¿Alguien puede indicarme una mejor documentación sobre convenciones de llamadas que MSDN? Además, ¿C solo tiene una convención de llamadas estándar? – Russel