c印记(九): 通用公共头文件

一、简介

在笔者从事嵌入式软件开发的这六七年时间里,因为涉及到多块硬件平台以及多种系统平台(如 linux,android,windows,freeRTOS等)。还有gcc和visual studio以及keil等构建工具,这些对基本数据类型的定义,以及编译动态库时对接口导出方式等存在大小不一的差异,所以,为了方便进行跨平台middleware软件的开发,就定义了一下的三个通用公共头文件。

注意:在这些头文件中,定义的数据类型或宏都是以 G 开头的,这里的G,就是General的首字母(通用,常规)

二、general_type.h

此头文件主要定义基础数据类型,API接口导出关键字(以宏模拟),inline关键字兼容宏(因visual studio中c语言是不支持inline关键字的),其具体头文件如下:

/*****************************************************************************
 * Name:general_type.h
 *
 * Purpose: standard header,and unified data type define
 *
 * Note: 'G' in macro and data type indicate 'general'
 *     
 * Version: 0.3
 *
 *
 *****************************************************************************/

#ifndef __GENERAL_TYPE_H__
#define __GENERAL_TYPE_H__
#include 
#include 

/**
 * general type define and some keyword Compatible.
 * The user can define the following macros in the build script to
 * control library's behavior.  If the user doesn't define a macro
 * in this list, general_type.h will define it.
 * DLL_EXPORT          - Define to 1 when compiling library itself
 *                           as a shared library.
 * G_FS_BITS           - Define to 64 when need to operation large file.
 * 
 */

/***************************************************************************
 * general data type define.
 ***************************************************************************/
typedef void*              GPHD;  //general instance handle type
typedef void*              GADR;  //general address type
typedef void*              GPTR;  //general pointer type
typedef char*              GSTR;  //general string type
typedef char               GCHR;  //general character type
typedef wchar_t            GWCH;  //general width character type.

//general signed integer type
typedef char               GS08;  //8  bits
typedef short              GS16;  //16 bits
typedef int                GS32;  //32 bits
typedef long long          GS64;  //64 bits

//general unsigned integer type
typedef unsigned char      GU08; //8 bits
typedef unsigned short     GU16; //16 bits
typedef unsigned int       GU32; //32 bits
typedef unsigned long long GU64; //64 bits

//general float type
typedef float              GFLT;
typedef double             GDBL;

//boolean type declaration
typedef GU32 GBOL;

#ifndef GTRUE /** boolean true */
#define GTRUE 1
#endif

#ifndef GFALSE /** boolean false */
#define GFALSE 0
#endif

/***************************************************************************
 * general data type limit(maximum and minmum) value define.
 ***************************************************************************/
#define GS08_MIN   (-127 - 1)
#define GS16_MIN   (-32767 - 1)
#define GS32_MIN   (-2147483647 - 1)
#define GS64_MIN   (-9223372036854775807LL - 1)
#define GS08_MAX   127
#define GS16_MAX   32767
#define GS32_MAX   2147483647
#define GS64_MAX   9223372036854775807LL
#define GU08_MAX   0xff
#define GU16_MAX   0xffff
#define GU32_MAX   0xffffffff
#define GU64_MAX   0xffffffffffffffffULL

/***************************************************************************
 * define extern "C" macro.
 ***************************************************************************/
#ifdef __cplusplus
#define G_EXTERN_C extern "C"
#else
#define G_EXTERN_C 
#endif

/***************************************************************************
 * macro define for specfial toolchain.
 ***************************************************************************/
#if defined(__GNUC__) /** !!!for gcc */

#define G_GCC_VERSION(maj,min) \
    ((__GNUC__ > (maj)) || (__GNUC__ == (maj) && __GNUC_MINOR__ >= (min)))

/** define API export  macro */
#if G_GCC_VERSION(4,0) //for gcc(version >= 4.0)
#define G_DLL_EXPORT __attribute__((visibility("default")))
#else
#define G_DLL_EXPORT
#endif

/** define operation system type */
#if defined(__linux__)
#if defined(__ANDROID__)
#define G_OS_ANDROID
#else
#define G_OS_LINUX
#endif
#endif

/** define operation system bit depth */
#if (__SIZEOF_POINTER__ == 4) //pointer size is 4 byte(treat as 32bits os)
#define G_OS_BITS  32
#elif (__SIZEOF_POINTER__ == 8)//pointer size is 8 byte(treat as 64bits os)
#define G_OS_BITS  64
#else
#error "!!unknown os bit depth!!"
#endif

#elif defined(_MSC_VER) /** !!!for visual studio */

/** compat the keyword 'inline' */
#if (_MSC_VER > 1200) && !defined (__cplusplus)
#define inline    _inline  /** to compat keyword 'inline' */
#endif

/** auto define API export macro */
#if !defined(DLL_EXPORT) && defined(_WINDLL) //todo,process _USRDLL,_AFXDLL
#define DLL_EXPORT
#endif

#if defined (DLL_EXPORT)
#define G_DLL_EXPORT __declspec(dllexport)
#else
#define G_DLL_EXPORT

#endif

/** operation system type and bit depth define */
#if defined(_WIN64)
#define G_OS_BITS  64
#define G_OS_WINDOWS
#elif  defined(_WIN32)
#define G_OS_BITS  32
#define G_OS_WINDOWS
#else 
#error "unknown system type and bit depth, compile with MSVC "
#endif

#else /** !!!for unknown toolchain */
///
#error "!!unspport this toolchain at now!!"
#endif /** !!! end of toolchin define */

/***************************************************************************
 * default macro define.
 ***************************************************************************/
/** the flag of file operation */
#if !defined(G_FS_BITS)
/** 
 * default enable large file operation, here just indicate os API,
 * whether support large file, Decision by file system.
 */
#define G_FS_BITS 64  
#endif


/***************************************************************************
 * common macro define.
 ***************************************************************************/

/** general api decorate macro */
#define G_API G_EXTERN_C G_DLL_EXPORT

/** general class decorate macro*/
#define G_CLASS G_DLL_EXPORT

/** path separator define */
#if defined(G_OS_WINDOWS)
#define PATH_SEPARATOR '\\'
#elif defined(G_OS_LINUX) || defined(G_OS_ANDROID)
#define PATH_SEPARATOR '/'
#else
#error "unknown system type"
#endif
/***************************************************************************
 * some special data type define.
 ***************************************************************************/

#endif //end of __GENERAL_TYPE_H__

三、general_macro.h

通用宏头文件中,主要定义的是操作,比较,读写,断言等等。

/*****************************************************************************
 * Name:general_macro.h
 *
 * Purpose:standard header,and unified mcaro define
 *
 * Warning:
 *     these macro cann't have any ++, -- in parameter.
 *
 *****************************************************************************/

#ifndef __GENERAL_MACRO_H__
#define __GENERAL_MACRO_H__

#include 
#include "general_type.h"

/***************************************************************************
 *math macro define
 ***************************************************************************/
#define GABS(a)             (((a) > 0) ? (a) : -(a))
#define GMIN(a, b)          ((a) < (b) ? (a) : (b))
#define GMAX(a, b)          ((a) > (b) ? (a) : (b))

/**make sure the range of v, between 'min' and 'max' */
#define GCLIP(v, min, max) GMIN(GMAX(v, min), max)

//fourcc macro define
#define GFCC(a, b, c, d)    (((GU32)a) | (((GU32)b) << 8) | (((GU32)c) << 16) | (((GU32)d) << 24))


/***************************************************************************
 *bytes operation macro define
 ***************************************************************************/
// read 2 bytes data by big endian 
#define GRB2(a)  ((GU16)((((GU08*)(a))[0] <<  8) | ((GU08*)(a))[1]))
// read 3 bytes data by big endian 
#define GRB3(a)  ((GU32)((((GU08*)(a))[0] <<  16) | (((GU08*)(a))[1] << 8) | ((GU08*)(a))[2]))
// read 4 bytes data by big endian 
#define GRB4(a)  ((GU32)((((GU08*)(a))[0] << 24) | (((GU08*)(a))[1] << 16) |  \
                (((GU08*)(a))[2] <<  8) | ((GU08*)(a))[3]))
// read 8 bytes data by big endian 
#define GRB8(a)  ((((GU64)((GU08*)(a))[0]) << 56) | (((GU64)((GU08*)(a))[1]) << 48) |  \
                (((GU64)((GU08*)(a))[2]) << 40)  | (((GU64)((GU08*)(a))[3]) << 32) |  \
                (((GU64)((GU08*)(a))[4]) << 24)  | (((GU64)((GU08*)(a))[5]) << 16) |  \
                (((GU64)((GU08*)(a))[6]) <<  8)  | (GU64)(((GU08*)(a))[7]))


// read 2 bytes data by little endian
#define GRL2(a)  ((GU16)(((GU08*)(a))[0] | (((GU08*)(a))[1] << 8)))
// read 3 bytes data by little endian
#define GRL3(a)  ((GU32)(((GU08*)(a))[0] | (((GU08*)(a))[1] << 8) | (((GU08*)(a))[2] <<  16)))
// read 4 bytes data by little endian
#define GRL4(a)  ((GU32)(((GU08*)(a))[0] | (((GU08*)(a))[1] <<  8) |  \
                (((GU08*)(a))[2] << 16) | (((GU08*)(a))[3] << 24)))
// read 8 bytes data by little endian
#define GRL8(a)  (((GU64)((GU08*)(a))[0]) | (((GU64)((GU08*)(a))[1]) << 8) |  \
                (((GU64)((GU08*)(a))[2]) << 16) | (((GU64)((GU08*)(a))[3]) << 24) |  \
                (((GU64)((GU08*)(a))[4]) << 32) | (((GU64)((GU08*)(a))[5]) << 40) |  \
                (((GU64)((GU08*)(a))[6]) << 48) | (((GU64)((GU08*)(a))[7]) << 56))


// write 2 bytes data as big endian
#define GWB2(a, b)  do{((GU08*)(a))[0] = (b) >> 8;((GU08*)(a))[1] = (b);}while(0)
// write 4 bytes data as big endian
#define GWB4(a, b)  do{((GU08*)(a))[0] = (b >> 24);((GU08*)(a))[1] = (b >> 16);  \
                    ((GU08*)(a))[2] = (b >> 8);((GU08*)(a))[3] = (b);}while(0)

// write 2 bytes data as little endian
#define GWL2(a, b)  do{((GU08*)(a))[0] = (b);((GU08*)(a))[1] = (b >> 8);}while(0)
// write 4 bytes data as little endian
#define GWL4(a, b)  do{((GU08*)(a))[0] = (b);((GU08*)(a))[1] = (b >> 8);       \
                    ((GU08*)(a))[2] = (b >> 16);((GU08*)(a))[3] = (b >> 24);}while(0)

// swap 2 bytes integer 
#define GSWAP2(a)  ((GU16)((((a) & 0xff00) >> 8) | (((a) & 0xff) << 8)))
// swap 4 bytes integer                 
#define GSWAP4(a)  ((((a) & 0xff) << 24) | (((a) & 0xff00) << 8) | \
                  (((a) >> 8) & 0xff00) | (((a) >> 24) & 0xff))

//write little endian data to a ptr unit in bytes
#define GPWL1(p, b) (*(p)++ = (GU08)(b))

#define GPWL2(p, var) do{*(p)++ = (GU08)((var)>>0);*(p)++ = (GU08)((var)>>8);} while(0) 

#define GPWL4(p, var) do{*(p)++ = (GU08)((var)>>0);*(p)++ = (GU08)((var)>>8);  \
                        *(p)++ = (GU08)((var)>>16);*(p)++ = (GU08)((var)>>24);}while(0) 

//write big endian data to a ptr unit in bytes
#define GPWB1(p, b) (*(p)++ = (GU08)(b)) 

#define GPWB2(p, var) do{*(p)++ = (GU08)((var)>>8);*(p)++ = (GU08)((var)>>0);}while(0)

#define GPWB4(p, var) do{*(p)++ = (GU08)((var)>>24);*(p)++ = (GU08)((var)>>16);  \
                        *(p)++ = (GU08)((var) >> 8); *(p)++ = (GU08)((var) >> 0);}while (0)

//write n bytes data to a ptr 
#define GPWN(p, buf, n) do{memcpy((p), (buf), (n)); ((GU08 *)(p)) += (n);}while(0)

/***************************************************************************
 *array operation macro define
 ***************************************************************************/
//get array element counts
#define GALEN(a) (sizeof(a) / sizeof((a)[0]))

/***************************************************************************
 * for normal variable value
 ***************************************************************************/
//set value to variable
#define GVSET(var, value) ((var) = (value))

//judagement var1 and var2 is equal
#define GVEQ(var1, var2) ((var1) == (var2))

//judagement var1 and var2 is not equal
#define GVNE(var1, var2) ((var1) != (var2))

//judagement var1 is less than(or equal) var2 
#define GVLE(var1, var2) ((var1) <= (var2))

//judagement var1 is less than var2
#define GVLT(var1, var2) ((var1) < (var2))

//judagement var1 is greater than(or equal) var2
#define GVGE(var1, var2) ((var1) >= (var2))

//judagement var1 is greater than var2
#define GVGT(var1, var2) ((var1) > (var2))

/***************************************************************************
 * structure operation macro
 ***************************************************************************/
//initialize structure
#define GSTRUCT_INIT(a)  memset(&(a), 0, sizeof(a))
//initialize structure with ptr
#define GSTRUCT_PTR_INIT(p) memset(p, 0, sizeof(*(p)))


/***************************************************************************
* assert operation macro
***************************************************************************/
//if not equal then do assert break;
#define GCEQ(val1, val2) assert(GVEQ(val1, val2))
#define GCLT(val1, val2) assert(GVLT(val1, val2))
#define GCHECK(val)      assert(val)

/***************************************************************************
* Branch prediction macro
***************************************************************************/
#ifdef __GNUC__
#define GLIKELY(p)   __builtin_expect(!!(p), 1)
#define GUNLIKELY(p) __builtin_expect(!!(p), 0)
#else
#define GLIKELY(p)   (!!(p))
#define GUNLIKELY(p) (!!(p))
#endif

#endif //end of __GENERAL_MACRO_H__

四、general_error.h

这个头文件是仿照openMax IL层接口定义中的错误类型定义方式实现的,主要是定义了一些常用的通用错误类型,并留有余地,可自定义一些扩展错误类型。

/*****************************************************************************
 * Name:general_error.h
 *
 * Purpose: standard header,and unified error type define
 *
 * Note: 'G' in macro and data type indicate 'general'
 *     
 * Version: 0.1
 *
 * Developer:
       wen.gu, 2016-06-23
 * Modified by:
 * 
 *
 *****************************************************************************/


#ifndef __GENERAL_ERROR_H__
#define __GENERAL_ERROR_H__

#include "general_type.h"

/***************************************************************************
 *
 * macro declaration
 *
 ***************************************************************************/

/***************************************************************************
 *
 * data structure declaration
 *
 ***************************************************************************/
/** 
 * The general_error_t enumeration defines the standard Errors.    
 * These errors should cover most of the common failure cases.  However,  
 * vendors are free to add additional error messages of their own as  
 * long as they follow these rules: 
 *
 *  1. Vendor error messages shall be in the range of 0x90000000 to 0x9000FFFF. 
 *
 *  2. Vendor error messages shall be defined in a header file provided 
 *     with the plugin/component/module/library.  No error messages are allowed
 *     that are not defined. 
 */
typedef enum general_error_e
{
    G_OK = 0,
    G_FAIL = -1,
    G_ErrorNone = G_OK,
    /** There were insufficient resources to perform the requested operation */  
    G_ErrorInsufficientResources = (GS32) 0x80001000,  
    /** There was an error, but the cause of the error could not be determined */  
    G_ErrorUndefined = (GS32) 0x80001001,

    /** The name string was invalid */
    G_ErrorInvalidName = (GS32)0x80001002,
    /** No target with the specified name string was found */
    G_ErrorNotFound = (GS32)0x80001003,
    /** One or more parameters were not valid */
    G_ErrorBadParameter = (GS32)0x80001004,
    /** The requested function is not implemented */
    G_ErrorNotImplemented = (GS32)0x80001005,
    /** The buffer was emptied before the next buffer was ready */
    G_ErrorUnderflow = (GS32)0x80001006,
    /** The buffer was not available when it was needed */
    G_ErrorOverflow = (GS32)0x80001007,
    /** The hardware failed to respond as expected */
    G_ErrorHardware = (GS32)0x80001008,
    /** havn't enough free memory in buffer */
    G_ErrorNoMemory = (GS32)0x80001009,
    /** some excecption about out of range */
    G_ErrorOutOfRange = (GS32)0x8000100A,


    /** No more indicies can be enumerated */
    G_ErrorNoMore = (GS32)0x8000100E,
    /** The target detected a version mismatch */
    G_ErrorVersionMismatch = (GS32)0x8000100F,
    /** The component is not ready to return data at this time */
    G_ErrorNotReady = (GS32)0x80001010,
    /** There was a timeout that occurred */
    G_ErrorTimeout = (GS32)0x80001011,
    /** this operation would block */
    G_ErrorWouldBlock = (GS32)0x80001012,

    /** need more data */
    G_ErrorNeedMoreData = (GS32)0x80001016,
    /** doesn't initialized */
    G_ErrorNoInit = (GS32)0x80001017,

    /** The values encapsulated in the parameter or config structure are not supported. */
    G_ErrorUnsupportedCommand = (GS32)0x80001019,
    /** The parameter or config indicated by the given index is not supported. */
    G_ErrorUnsupportedInvokeId = (GS32)0x8000101A,

    /** EOF  error */
    G_ErrorEOF = (GS32)0x8000101B,
    G_ErrorInvalidOperation = (GS32)0x8000101C, /** invalid operation */

    /** Reserved region for introducing general Standard Extensions */
    G_ErrorExtensions = (GS32)0x8F000000, 
    /** Reserved region for introducing Vendor Extensions */
    G_ErrorStartUnused = (GS32)0x90000000, 
    G_ErrorMax = 0x7fffffff   
}general_error_t;

/***************************************************************************
 *
 * API declaration
 *
 ***************************************************************************/



#endif //end of __GENERAL_ERROR_H__

五、总结

以上三个文件,都是笔者自己平常使用的基本头文件,当然其中也并非十全十美,不过有此三个基本文件,在编写代码时可以省却不少功夫,尤其是编写一些跨平台的middleware层的代码更为方便。

在以后的工作中或者自己写些代码的时候,会不断的积累完善此三个头文件。除了头文件之外,还会尝试将一些基础的,通用的接口或容器等等归纳起来,实现一个小型的框架性质的library。

你可能感兴趣的:(c/c++)