Problem with size of enum variables

mborgerson

Well-known member
While working on my driver for the FLIR Lepton 3.5, I've run into an issue with the library I'm using to control the camera through the I2C interface: LeptonSDKEmb32OEM.

Code:
Example  enum and structure:

// a typical enum typedef:
typedef enum LEP_SYS_ENABLE_E_TAG
{
   LEP_SYS_DISABLE = 0,
   LEP_SYS_ENABLE,
   LEP_END_SYS_ENABLE 
}LEP_SYS_ENABLE_E, *LEP_SYS_ENABLE_E_PTR;


// The function to get shutter status uses this structure:
typedef struct LEP_SYS_FFC_SHUTTER_MODE_OBJ_T_TAG
{
   LEP_SYS_FFC_SHUTTER_MODE_E shutterMode;   /* defines current mode */
   LEP_SYS_SHUTTER_TEMP_LOCKOUT_STATE_E   tempLockoutState;
   LEP_SYS_ENABLE_E videoFreezeDuringFFC;
   LEP_SYS_ENABLE_E ffcDesired;              /* status of FFC desired */
   LEP_UINT32 elapsedTimeSinceLastFfc;       /* in milliseconds x1 */
   LEP_UINT32 desiredFfcPeriod;              /* in milliseconds x1 */
   LEP_BOOL       explicitCmdToOpen;             /* true or false */
   LEP_UINT16 desiredFfcTempDelta;           /* in Kelvin x100  */
   LEP_UINT16 imminentDelay;                 /* in frame counts x1 */
}

The first four elements are enums (with '_E' at the end of the name).

When I compile for the T4.1, I find that the size of the structure is reported as 20 bytes. That is consistent with the compiler using just one byte per enum variable. The problem is that the code for this library was written for a 32-bit PC and assumes that each enum variable will occupy 32 bits, or 4 bytes.

The code I want to run is this function:

Code:
LEP_RESULT LeptonSDKEmb32OEM::LEP_GetSysFfcShutterModeObj( LEP_CAMERA_PORT_DESC_T_PTR portDescPtr,
                                        LEP_SYS_FFC_SHUTTER_MODE_OBJ_T_PTR shutterModeObjPtr ){
   LEP_RESULT result = LEP_OK;
   LEP_UINT16 attributeWordLength = 16;   // NOTE request for 16 words of returned atributes

   if( shutterModeObjPtr == NULL ) {
      return( LEP_BAD_ARG_POINTER_ERROR );
   }
 // call library function to read attributes with I2C interface
   result = LEP_GetAttribute( portDescPtr,
                              ( LEP_COMMAND_ID )LEP_CID_SYS_FFC_SHUTTER_MODE_OBJ,
                              ( LEP_ATTRIBUTE_T_PTR )shutterModeObjPtr,
                              attributeWordLength );
   return( result );
}

You can see that the code requests 16 words, or 32-bytes of data. When the command tries to store that 32-bytes of data, it writes past the end of the 20-byte variable, causing a crash.

As a workaround, I modified the definitions of the enums used as follows:

Code:
typedef enum LEP_SYS_ENABLE_E_TAG
{
   LEP_SYS_DISABLE = 0,
   LEP_SYS_ENABLE, 
   LEP_END_SYS_ENABLE = 65540  // forces use of 32 bits for enum
 
}LEP_SYS_ENABLE_E, *LEP_SYS_ENABLE_E_PTR;

With this modification, the size of the structure changes to 32, and reading the data doesn't cause an overflow and the function returns the desired results.


My question is: Can I set up the Teensy compiler to make all enums 32 bits just in the code in this library?
(I don't want to override the default enum size as I'm worried that it could cause problems with other libraries.)
 
Use
C++:
typedef enum LEP_SYS_ENABLE_E_TAG: uint32_t {
    LEP_SYS_DISABLE = 0,
   LEP_SYS_ENABLE,
} LEP_SYS_ENABLE_E, *LEP_SYS_ENABLE_E_PTR;
so that the underlying type of the enum is an unsigned 32-bit integer. You can use any other integral type besides uint32_t the same way.

This is valid C++ since C++11.
 
The workaround you've already found is probably the "best" solution.
You could try passing "-fno-short-enums" to the compiler to force it to use 32-bits for every enum, but it's still not guaranteed (the C standard says the compiler is free to use whatever size it thinks is necessary) and may break any precompiled code, like the included C standard library.
Alternatively replace enum variables in structs with the appropriate fixed-size integer variables.
 
C and C++ are completely different programming languages. The snippet shown uses C++ syntax, and does not compile as C, not even as C23.

I stand by my claim of using the C++11 and later syntax for specifying the underlying type for the enum type, because the rest of the code is already C++ and not C.
 
Back
Top