Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

243
Vistas
definición de tipo de un puntero reconocido por C a una clase interna de C++

Tengo una clase que quiero compartir entre C y C++, donde C solo puede obtenerla como un puntero. Sin embargo, debido a que es una clase interna, no se puede declarar hacia adelante. En cambio, esto es lo que hace nuestro código actual en un archivo de encabezado común:

 #ifdef __cplusplus class Container { public: class Object { public: int x; }; }; typedef Container::Object * PObject; #else typedef void* PObject; #endif

Parece que esto viola la regla de una definición (ODR), porque C y C++ ven una definición diferente usando #ifdef . Pero debido a que esto es un puntero, no estoy seguro de si esto crea un problema real o no. C solo usa el puntero para pasarlo a las funciones de C++, no hace nada directamente con él. Por ejemplo, este código en el archivo de encabezado común:

 #ifdef __cplusplus extern "C" { #endif int object_GetX(PObject pObject); #ifdef __cplusplus } #endif /* __cplusplus */

Así es como lo implementamos en el archivo C++:

 int object_GetX(PObject pObject) { return pObject->x; }

Mis preguntas son:

  1. ¿Violar la ODR de esta manera causaría algún problema real?
  2. Si es así, ¿hay otra forma conveniente de compartir la clase con C?
over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

En primer lugar, los punteros de alias de tipo suelen ser una receta para los problemas.
no lo hagas

En segundo lugar, la clase "interna" es un concepto usado en exceso, por lo que mi primer reflejo sería considerar si es realmente necesario.

Si es necesario, puede definir un tipo vacío opaco y derivar de él para alguna seguridad de tipo:

En un encabezado compartido:

 struct OpaqueObject; #ifdef __cplusplus extern "C" { #endif int object_GetX(OpaqueObject* pObject); #ifdef __cplusplus } #endif /* __cplusplus */

En un encabezado de C++:

 struct OpaqueObject {}; class Container { public: class Object : public OpaqueObject { public: int x; }; };

Implementación:

 int object_GetX(OpaqueObject* pObject) { return static_cast<Container::Object*>(pObject)->x; }
over 4 years ago · Santiago Trujillo Denunciar

0

¿Violar la ODR de esta manera causaría algún problema real?

¿"Problemas reales"? Quizás. Tal vez no.

No existe una "regla ODR mixta C/C++". Las reglas están "contenidas" dentro de un lenguaje de programación, las especificaciones están escritas para un lenguaje de programación. C++ tiene sus propias reglas y C++ ihas regla ODR. C tiene sus propias reglas y C no sabe nada sobre ODR. Otros lenguajes de programación tienen sus propias reglas.

No está violando ODR en C ++: C ++ ve una sola definición de Contenedor en todas partes.

El material en extern "C" usa la convención de llamadas C, que podría suponer que también se adhiere al lenguaje C. En este caso, simplemente está violando la regla https://port70.net/~nsz/c/c11/n1570.html#6.5.2.2p9 . Digamos que esto es como ODR en C para funciones.

Si no, estás violando algo entre idiomas, eso sería ABI. Pasas el valor de un puntero void * del lado C y tu función lee un valor del puntero Container::Object * del lado C++. Eso podría estar permitido por el ABI específico que usan sus compiladores, podría no estar especificado. El enfoque seguro sería asumir que no está permitido.

¿Hay otra forma conveniente de compartir la clase con C?

El lenguaje C también ofrece verificación de tipo estático al igual que C++, pero al usar void * básicamente lo está desactivando. No mezcle C ++ con C. Solo tenga un nombre único diferente para el lado C, estará mucho menos confundido.

Además, pObject vs PObject ? ¡Tu turno debe ser rápido!

 // object.hpp #ifdef __cplusplus class Container { public: class Object { public: int x; }; }; typedef Container::Object PObject; extern "C" { #endif struct C_PObject { void *pnt; }; int object_GetX(struct C_PObject obj); // ... // object_c.cpp PObject *object_from_c(struct C_PObject obj) { return reinterpret_cast<PObject *>(obj.pnt); } extern "C" int object_GetX(struct C_PObject obj) { return object_from_c(obj)->x; }
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda