Compartir un archivo de encabezado multiplataforma

I. Introducción

Cuando normalmente escribimos código, especialmente cuando fabricamos ruedas (proporcionando archivos de biblioteca para otros ), encontraremos varios escenarios de demanda:

  1. Algunas personas necesitan usarlo en un sistema Linux, algunas personas necesitan usarlo en un sistema Windows;
  2. Algunas personas usan el lenguaje C para desarrollar, algunas personas usan C ++ para desarrollar;
  3. Algunas personas usan bibliotecas dinámicas, algunas personas usan bibliotecas estáticas;

Especialmente en el sistema Windows , la función exportada en el archivo de la biblioteca necesita usar _declspec (dllexport) para declarar la función, y el usuario necesita usar _declspec (dllimport) para declarar la función al importar , ¡lo cual es muy problemático!

Este breve artículo comparte un archivo de encabezado . Con este archivo de encabezado, más algunas macros pasadas durante la compilación , puede manejar perfectamente las diversas necesidades que acabamos de mencionar.

En segundo lugar, el archivo de encabezado

Simplemente cargue el código directamente, puede intentar analizarlo primero y luego analizaremos diferentes escenarios de uso uno por uno .

El propósito principal de este archivo de encabezado es definir una macro: MY_API y luego agregar esta macro a la declaración de cada función o clase que necesita exportarse en el archivo de biblioteca . P.ej:

void MY_API do_work();

Aquí está el archivo de encabezado:

_Pragma("once")

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
    #define MY_WIN32
#elif defined(linux) || defined(__linux) || defined(__linux__)
    #define MY_LINUX
#endif

#if defined(MY_WIN32)
    #ifdef MY_API_STATIC
      #ifdef __cplusplus
         #define MY_API extern "C"
      #else
         #define MY_API
      #endif
   #else
      #ifdef MY_API_EXPORTS
         #ifdef __cplusplus
            #define MY_API extern "C" __declspec(dllexport)
         #else
            #define MY_API __declspec(dllexport)
         #endif
      #else
         #ifdef __cplusplus
            #define MY_API extern "C" __declspec(dllimport)
         #else
            #define MY_API __declspec(dllimport)
         #endif
      #endif
   #endif
#elif defined(MY_LINUX)
    #ifdef __cplusplus
       #define MY_API extern "C"
    #else
       #define MY_API
    #endif
#endif

Tres, la macro predefinida

Suponga que necesita escribir un archivo de biblioteca y proporcionarlo para que otros lo utilicen. Después de definir lo anterior, el primer documento, otros documentos deben incluir este archivo de encabezado.

1. Definición de macro de plataforma

Las diferentes plataformas tienen definiciones de macro correspondientes predefinidas, por ejemplo:

Plataforma Windows: WIN32, _WIN32, WIN32 ;
Plataforma Linux: linux, __linux, linux ;

En una plataforma determinada, es posible que estas macros no estén todas definidas, es posible que solo una de ellas esté definida.

Por unidad, unificamos estas posibles macros al principio del archivo de encabezado, y definimos nuestra propia definición de macro de plataforma: MY_WIN32 o MY_LINUX. Cuando necesitemos distinguir entre diferentes plataformas más adelante, usamos esta autodefinida. Macro de plataforma .

Por supuesto, puedes seguir expandiendo otras plataformas, como: MY_MAC, MY_ARM, etc.

2. Definición de macro del compilador

Si usa C ++ al escribir el código de la biblioteca , y el usuario usa el lenguaje C , entonces necesita hacer una declaración "C" externa para la función de la biblioteca , de modo que el compilador no vuelva a escribir el nombre de la función .

La macro predefinida del compilador g ++__cplusplus , por lo tanto, en el archivo de encabezado, usa esta macro para MY_APIagregar la instrucción "C" externa .

Cuarto, análisis de escenarios de la plataforma Windows

1. Compila y genera archivos de biblioteca

(1) Generar biblioteca estática

En la biblioteca estática, no hay __declspec(dllexport/dllimport)declaración, solo es necesario distinguir el compilador (gcc o g ++), definir las opciones del compilador de macros MY_API_STATIC, puede obtener las finales MY_APIson:

compilador gcc: #define MY_API
compilador g ++: #define MY_API extern "C"

(2) Generar biblioteca dinámica

Al compilar opciones, defina macros MY_API_EXPORTS, por lo que el resultado se MY_APIconvierte en:

compilador gcc: #define MY_API __declspec (dllexport)
compilador g ++: #define MY_API extern "C" __declspec (dllexport)

2. Usando la biblioteca

Al usar la aplicación de biblioteca , también debe incluir este código en el archivo de encabezado y luego agregar una variedad de opciones del compilador de macros definidas para generar las MY_APIdefiniciones de macros correspondientes .

(1) Usar biblioteca estática

Debe definirse en las opciones de compilación MY_API_STATIC, puede obtener las finales MY_APIson:

compilador gcc: #define MY_API
compilador g ++: #define MY_API extern "C"

(2) Usar biblioteca dinámica

No requiere ninguna macro definida en las opciones de compilación, puede obtener las finales MY_APIson:

compilador gcc: #define MY_API extern "C" __declspec (dllimport)
compilador g ++: #define MY_API __declspec (dllimport)

Esto es equivalente a declarar la función de biblioteca de importación .

Cinco, análisis de escenarios de la plataforma Linux

Es mucho más simple bajo la plataforma Linux, solo necesita prestar atención al problema del compilador y no hay distinción entre exportar e importar.


Los buenos artículos deben enviarse ; cuanto más compartas, más afortunado eres.


Lectura recomendada

1. Puntero del lenguaje C: desde el principio de nivel inferior hasta habilidades sofisticadas, use gráficos y código para ayudarlo a explicarlo en profundidad
2. El principio de depuración de nivel inferior de gdb original es muy simple
3. Análisis paso a paso: cómo usar C para implementar la programación orientada a objetos
4. Todo lo dicho La arquitectura del software debe dividirse en capas y en módulos, y qué se debe hacer específicamente (1)
5. Se dice que la arquitectura del software debe dividirse en capas y en módulos, y qué debe hacerse específicamente (2)

Supongo que te gusta

Origin blog.csdn.net/u012296253/article/details/115366952
Recomendado
Clasificación