¿Qué problemas puedo esperar al comstackr el código C con un comstackdor de C ++?

Si toma una base de código C existente y la comstack con un comstackdor C ++, ¿qué tipo de problemas puede esperar que surjan? Por ejemplo, creo que asignar un entero a un valor con un tipo enumerado fallará en C ++, mientras que es legal (si es un poco desagradable) en C.

Si no envuelvo todos mis archivos C en extern C { ... } , ¿voy a cambiar de nombre donde menos lo espero? ¿Hay alguna razón por la que realmente no debería hacer esto?

Para el fondo, tenemos una gran base de código escrita en C. Durante algunos años hemos estado saltando a través de aros para hacer cosas que vendrían naturalmente a través de C ++ (herencia homebrewe, por ejemplo). Nos gustaría comenzar a avanzar hacia C ++, pero de forma gradual; obtener nuestro marco similar al de CORBA para soportarlo, y refaccionar los módulos a medida que avanzamos para aprovechar el enfoque más natural que C ++ proporcionaría.

He hecho algo así una vez. La principal fuente de problemas fue que C ++ es más estricto con los tipos, como sospechabas. Tendrá que agregar moldes donde void * se mezclan con punteros de otros tipos. Como asignando memoria:

 Foo *foo; foo = malloc(sizeof(*foo)); 

Lo anterior es un código C típico, pero necesitará un molde en C ++:

 Foo *foo; foo = (Foo*)malloc(sizeof(*foo)); 

Hay nuevas palabras reservadas en C ++, como “clase”, “y”, “bool”, “captura”, “eliminar”, “explícito”, “mutable”, “espacio de nombres”, “nuevo”, “operador”, “o”, “privado”, “protegido”, “amigo”, etc. No se pueden usar como nombres de variables, por ejemplo.

Los anteriores son probablemente los problemas más comunes cuando comstack código C antiguo con un comstackdor C ++. Para obtener una lista completa de incompatibilidades, consulte Incompatibilidades entre ISO C y ISO C ++ .

También preguntas sobre el cambio de nombre. En ausencia de envoltorios “C” externos, el comstackdor C ++ destruirá los símbolos. No es un problema siempre que use solo un comstackdor de C ++, y no confíe en dlsym () o algo así para extraer símbolos de las bibliotecas.

Consulte Incompatibilidades entre ISO C y ISO C ++ para obtener una lista muy detallada de todas las incompatibilidades. Hay muchos problemas sutiles, incluidos algunos que no se manifiestan inmediatamente en un error de comstackción. Por ejemplo, un problema que puede ser un problema es el tamaño de las constantes de los caracteres:

 // In C, prints 4. In C++, prints 1 printf("%d\n", sizeof('A')); 

Si no envuelvo todos mis archivos C en “Extern C {…}”, ¿tendré que cambiar el nombre donde menos lo espero?

Te muerde cuando intentas unir C y C ++.

He escrito muchos archivos de encabezado que contienen:

 #ifdef __cplusplus extern "C" { #endif // rest of file #ifdef __cplusplus } #endif 

Después de un tiempo se fusiona con el texto repetitivo de incluir múltiples y deja de verlo. Pero debes tener cuidado donde lo pones, generalmente pertenece después de que cualquier incluye tu encabezado.

¿Hay alguna razón por la que realmente no debería hacer esto?

Si está seguro de que no combinará C y C ++, entonces no hay razón para hacerlo que yo sepa. Pero con la migración gradual que describes, es esencial para cualquier cosa con una interfaz publicada que los componentes C y los componentes C ++ necesiten usar.

La gran razón para no hacerlo es que le impide sobrecargar funciones (al menos en esos encabezados). Es posible que desee hacer eso una vez que haya migrado todo su código a C ++ y haya comenzado a mantenerlo / refactorizarlo / ampliarlo.

Otro ejemplo: no hay una conversión implícita de Ints a Enums en C ++, mientras que hay uno en C. Necesitarás un elenco si realmente quieres hacerlo en C ++.

Lo he hecho antes de usar MSVC; si usa MSVC, una buena estrategia es:

  1. Establezca archivos individuales para comstackrlos como CPP, de esa forma puede pasar gradualmente a un comstackdor CPP.
  2. Trabaje a través de archivo por archivo usando ctrl + f7 solo para comstackr ese archivo.
  3. En lugar de convertir todos los mallocs, puede crear una versión de plantilla en su lugar

foo = (Foo *) malloc (sizeof (* foo));

se convierte

 foo = malloc(); 

Y, por supuesto, puede tener una sobrecarga para los casos en los que desea un Foo + n bytes

También recomendaría cambiar las asignaciones de memoria para usar RAII siempre que sea posible, encontré que algunas funciones eran bastante complejas, por lo que cambiar a RAII era demasiado alto, en la mayoría de los casos fue lo suficientemente simple de hacer.

En general, no tendrás ningún problema en absoluto. Sí, hay algunas incompatibilidades entre C y C ++, pero no parecen surgir con tanta frecuencia a excepción del malloc casting mencionado anteriormente, que es bastante trivial de arreglar.

He comstackdo y utilizado con éxito las siguientes bibliotecas C de código abierto como C ++:

  • el analizador Expat XML
  • el rasterizador de fonts FreeType2
  • libjpeg: maneja imágenes JPEG
  • libpng: maneja imágenes PNG
  • la biblioteca de compresión Zlib

La parte más difícil fue agregar contenedores de espacio de nombres, lo que llevó algunas horas, en gran parte debido a las declaraciones #include enterradas profundamente en el código, que tenía que estar fuera del espacio de nombres C ++.

¿Por qué hice esto? Porque vendo una biblioteca comercial que las personas estaban vinculando directamente en sus aplicaciones; y a veces sus aplicaciones estaban vinculadas a otras versiones de Expat, FreeType, etc. Esto causó errores de símbolo definido de forma múltiple. Lo más limpio que podía hacer era mover todo dentro de mi biblioteca y esconderlo en mi espacio de nombres.

Sin embargo, no hice eso con todas las bibliotecas de código abierto que uso. Algunos todavía no han provocado conflictos, y no he podido solucionarlos, lo cual, aunque sin problemas, es bastante tedioso. La excepción interesante es SQLite, que no pude comstackr en C ++. Así que hice una búsqueda masiva y reemplazo, agregando un prefijo (el nombre de mi producto) a cada símbolo visible externamente. Eso resolvió el problema de mi cliente.

C ++ tiene una comprobación de tipos más estricta, por lo que es posible que deba agregar un molde a cada llamada a malloc / realloc / calloc.

Intenta comstackr con un comstackdor C ++:

 typedef enum{ false = 0, true = 1} bool;