2010-04-06 10 views
6

Basado en this question Entiendo el propósito del constructo al vincular bibliotecas C con código C++. Supongamos ahora lo siguiente:¿Cuál es el efecto de declarar "extern" C "'en el encabezado de una biblioteca compartida de C++?

Tengo una biblioteca compartida '.so' compilada con un compilador C++. El encabezado tiene un 'typedef stuct' y un número de declaraciones de función. Si el encabezado incluye la declaración externa "C" ...

#ifdef __cplusplus 
extern "C" 
{ 
#endif 

    // typedef struct ...; 
    // function decls 

#ifdef __cplusplus 
} 
#endif 

... ¿cuál es el efecto? Específicamente, me pregunto si hay efectos secundarios perjudiciales de esa declaración ya que la biblioteca compartida está compilada como C++, no como C.

¿Hay alguna razón para tener la declaración externa "C" en este caso?

+0

¿Su biblioteca solo se llamará desde C++ o también necesita que su biblioteca se llame desde C? –

Respuesta

11

Esto es importante para que el compilador no nombre mangle. C++ utiliza el cambio de nombre para diferenciar las funciones con sobrecargas del operador.

Run "/ usr/bin/nm" contra un binario para ver lo que hace C++ con sus nombres de función: _ZSt8_DestroyIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEEiEvT_S7_SaIT0_E

extern "C" evita que el nombre mangling.

IIRC, que hace posible que el programa enlace dinámicamente en símbolos en tiempo de ejecución. Es común para las arquitecturas de tipo "complemento".

+0

Gracias por la información.Estaba pensando en ello desde la perspectiva del cliente, incluido el encabezado, y no la biblioteca que exporta los nombres. –

4

Al compilar C++ el nombre del método cambios (mangling) - y usted no será capaz de llamar a ese método de otro DLL/EXE que utiliza C.

Con el fin de mantener a la clase y el método nombre que usted necesita compilarlos como "C" sin cambiar el nombre.

La biblioteca sigue siendo una biblioteca C++ pero expone algunas de sus declaraciones (la del bloque externo "c") como métodos C.

3

La #ifdef declaración extern guardada es para indicar a los vinculadores de C que los símbolos tienen entradas de tabla de símbolos C (no desactivadas). El #ifdef asegura que no hay ningún efecto en la unidad de código (archivo) compilada por un compilador de C.

0

un perjuicio para el uso extern "C" para una API C++ es que le impide tener sobrecargas de función:

extern "C" 
{ 
    // ILLEGAL - C linkage does not support function overloading 
    void foo(int x); 
    void foo(const char *str); 
} 
+1

El punto de utilizar 'extern" C "' es que tanto el código C como el código C++ compartan una API, y C es el mínimo común denominador, por lo que debe cumplir con las reglas que el compilador C impone. Si * fuera * una API C++, entonces no usaría 'extern" C "' y solo compilaría con un compilador C++ y todo estaría bien. – quamrana

+1

@quamrana - y su pregunta es "¿cuál es el efecto de una biblioteca compartida de C++". No está claro a partir de la pregunta si necesita poder llamar a su biblioteca desde el código C. –

0

El #ifdef en el ejemplo significa que sólo un compilador de C++ ver el extern envolver el archivo de cabecera que significará que producirá nombres no destrozados. Un compilador de C no ve el extern (que no entendería), pero siempre produce nombres no truncados.

Esto significa que ambos compiladores C y C++ producirán los mismos símbolos en sus archivos de objetos, por lo que cualquier compilador produce código objeto para las funciones declaradas, todos los archivos de objetos se vincularán satisfactoriamente porque los símbolos tienen el mismo enlace y el mismo nombre .

No debe haber implicaciones para vincular estáticamente o vincular con una biblioteca compartida.

Cuestiones relacionadas