Usando la biblioteca C ++ en código C


102

Tengo una biblioteca C ++ que proporciona varias clases para administrar datos. Tengo el código fuente de la biblioteca.

Quiero extender la API de C ++ para admitir llamadas a funciones de C para que la biblioteca se pueda usar con código C y código C ++ al mismo tiempo.

Estoy usando la cadena de herramientas GNU (gcc, glibc, etc.), por lo que el soporte de lenguaje y arquitectura no es un problema.

¿Hay alguna razón por la que esto no sea técnicamente posible?

¿Hay alguna trampa de la que deba tener cuidado?

¿Hay recursos, código de ejemplo y / o documentación disponible al respecto?


Algunas otras cosas que he descubierto:

  1. Utilice lo siguiente para ajustar los encabezados de C ++ que deben utilizar el código C.

#ifdef __cplusplus
extern "C" {  
#endif  
//  
// Code goes here ...  
//  
#ifdef __cplusplus  
} // extern "C"  
#endif
  1. Mantenga las interfaces C ++ "reales" en archivos de encabezado separados que no estén incluidos en el principio C. Piense en PIMPL aquí. Usar #ifndef __cplusplus #errorcosas ayuda aquí a detectar cualquier locura.
  2. Cuidado con los identificadores de C ++ como nombres en código C
  3. Enumeraciones que varían en tamaño entre los compiladores de C y C ++. Probablemente no sea un problema si está utilizando la cadena de herramientas GNU, pero aún así, tenga cuidado.
  4. Para estructuras, siga el siguiente formulario para que C no se confunda.

    typedef struct X { ... } X
  5. Luego use punteros para pasar objetos de C ++, solo deben declararse en C como estructura X donde X es el objeto de C ++.

Todo esto es cortesía de un amigo que es un mago en C ++.


5
Un poco tarde, pero escribí un pequeño tutorial sobre el contenedor C para C ++: teddy.ch/c++_library_in_c
Teddy

Respuestas:


69

Sí, esto es ciertamente posible. Necesitará escribir una capa de interfaz en C ++ que declare funciones con extern "C":

extern "C" int foo(char *bar)
{
    return realFoo(std::string(bar));
}

Luego, llamará foo()desde su módulo C, que pasará la llamada a la realFoo()función que está implementada en C ++.

Si necesita exponer una clase C ++ completa con miembros de datos y métodos, entonces puede que necesite hacer más trabajo que este simple ejemplo de función.


¿Debería extern "C"colocarse solo en declaraciones (y no en definiciones)? Porque mencionaste "la capa que declara funciones", pero tu código de muestra también es una definición. En otras palabras, ¿deberíamos colocarlo en archivos de encabezado o archivos de origen? (¿O ambos?)
kyriakosSt

@KyrSt: Si tiene un archivo de encabezado con una declaración de función, al menos debe colocarlo extern "C"allí. Su compilador le dirá si también debe incluirlo en la definición.
Greg Hewgill

23

C ++ FAQ Lite: "Cómo mezclar código C y C ++" .

Algunas trampas se describen en las respuestas a estas preguntas:

  • [32.8] ¿Cómo puedo pasar un objeto de una clase C ++ a / desde una función C?
  • [32.9] ¿Puede mi función C acceder directamente a los datos de un objeto de una clase C ++?

12

Problema principal: las excepciones no se pueden detectar en C. Si existe la posibilidad de que surja una excepción en el código C ++, escriba su código C o sus envoltorios C ++ con mucho cuidado. Por el contrario, los mecanismos de excepción (es decir, longjump) en el código C (como se encuentran en varios lenguajes de programación) no son necesarios para invocar destructores para objetos C ++ en la pila.


2
Un gran punto sobre las llamadas de salto largo. Si bien no los uso directamente, los marcos de prueba que uso los implementan. Algo para tener en cuenta. Gracias
Misha M

3

puede mezclar código C / C ++. Si su función main () está en C ++, entonces solo necesita asegurarse de que sus funciones c estén declaradas

extern "C"

Si su principal es C, entonces probablemente esté bien, excepto por las variables estáticas. Se supone que cualquier constructor con sus variables estáticas debe llamarse antes del inicio de main (). Esto no sucederá si C es tu principal. Si tiene muchas variables estáticas, lo mejor que puede hacer es reemplazar las variables estáticas con singletons.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.