2011-12-18 11 views
5

Tengo un código que se compila en una biblioteca (dll, biblioteca estática, etc.). Quiero que el usuario de esta biblioteca use alguna estructura para pasar algunos datos como parámetros para la función de la biblioteca. Pensé en declarar la estructura en el archivo de encabezado de la API.Definición de estructura en el archivo de encabezado de una biblioteca y diferencias de compilación

  • ¿Es seguro hacerlo, teniendo en cuenta la compilación con diferentes compiladores, con respecto a la alineación de la estructura u otras cosas que no pensé?
  • ¿Requerirá el uso del mismo compilador (y banderas) para la biblioteca y su usuario?

Pocas notas:

  1. que consideran dando al usuario un puntero y establecer toda la estructura a través de funciones en la biblioteca, pero esto hará que la API realmente no cómodo de usar.
  2. Esta pregunta es sobre C, aunque sería bueno saber si hay una diferencia en C++.

Respuesta

2

Si se trata de una biblioteca normal/estática, la biblioteca y la aplicación se deben compilar utilizando el mismo compilador. Hay algunas razones para esto que me ocurre:

  1. diferentes compiladores (como en diferentes marcas o compiladores para diferentes plataformas) normalmente no entienden los formatos de cada uno de objeto y de la biblioteca.
  2. No desea compilar diferentes partes del mismo programa utilizando diferentes tipos (p. Ej., Caracteres firmados o no firmados), tamaños de letra (por ejemplo, largo = 32 contra 64 bits), alineación y embalaje, y probablemente algunas otras cosas, todas que están permitidos por el estándar C para variar. Mezclar y combinar esas cosas suele ser algo malo.

Puede, sin embargo, a menudo utilizar versiones ligeramente diferentes del mismo compilador para compilar la biblioteca y la aplicación que lo utiliza. Por lo general, está bien. Sin embargo, a veces hay cambios que rompen el código.

Puede implementar alguna función de "inicialización" en ese archivo de encabezado (declarado como static inline) que aseguraría que los tipos, tamaños de tipo, alineación y empaque son los mismos que los esperados por la biblioteca compilada. La aplicación que usa esta biblioteca debería llamar a esta función antes de usar cualquier otra parte de la biblioteca. Si las cosas no son las mismas, la función debe fallar y provocar la finalización del programa, posiblemente con una buena descripción textual de la falla. Esto no resolverá por completo el problema de tener compiladores algo incompatibles, pero puede evitar malfuncionamientos silenciosos y misteriosos. Algunas cosas se pueden verificar con las directivas #if y #ifdef del preprocesador y causar errores de compilación con #error.

Además, los problemas de empaquetado de estructuras se pueden aliviar insertando bytes de relleno explícitos en las declaraciones de estructura y forzando el empaquetado ajustado (por ej.utilizando #pragma pack, que es compatible con muchos compiladores). De esta forma, si los tamaños de letra son iguales, no importará cuál sea el empaque predeterminado.

Puede aplicar lo mismo a las DLL también, pero realmente debe esperar que la aplicación de llamada haya sido compilada con un compilador diferente y no dependa de que los compiladores sean los mismos.

+0

Gracias por la respuesta detallada. Me diste algunas cosas nuevas en las que pensar. – MByD

0

Todas las API de Windows arrojan las estructuras como locos, así que obviamente esto es algo que se hace todos los días y funciona. Por supuesto, esto no significa que sus inquietudes no sean válidas :) Sugeriría que los campos de su estructura tengan tipos de ancho explícitos (int32_t etc.) y tal vez especifiquen explícitamente que el embalaje se rompa en cualquier compilador, excepto el suyo , es decir,

#if defined(_MSC_VER) 
#pragma pack(0) 
#elif defined ... handle gcc 
#else 
FAIL // fail compilation on unsupported platform 
#endif 
+0

Las API de Windows * definitivamente * definen el embalaje explícitamente para sus estructuras. Simplemente lo encapsulan/confunden en encabezados. Probablemente esté * seguro * haciendo esto, pero se recomienda encarecidamente ejercitar la atención. –

+0

gcc admite el paquete #pragma. –

Cuestiones relacionadas