Forums

How to use same structure for two different platforms?

Started by janii May 24, 2011
We program Freescale PowerPC Microcontrollers in 'C' language.

Following structure declared by lower layer library is as follows:  It is
instantiated by top
layer application.  A pointer to this structure is passed to lower layer
library functions.


typedef struct
{
   /* Initialization Function */
   void (*fc_init) (alg_work_t *work, alg_cfg_t *config);

   /* Main Function */
   void (*fc_main) (alg_work_t *work, alg_cfg_t *config);

   /* This structure is used to read the raw frequency/direction from the
hardware */
   frqqd_config_t input_config;

   /* some member */
   int member1;

} spdwdir_config_t;


typedef struct
{
   int tpu;
   int primary_channel;
   int secondary_channel;
   int edge;
   int tcr;
   int tpu_priority;
   int debounce_time;
   unsigned int max_period;
   unsigned int min_period;
   unsigned int timeout;

} frqqd_config_t;



In new platform, structure frqqd_config_t does not exist.  Top layer
application still needs to pass
following members from this structure to lower layer library functions:

typed struct
{
   void * primary_channel
   int debounce_time;
   unsigned int max_period;
   unsigned int min_period;
   unsigned int timeout;

} app_frqqd_config_t;



POSSIBLE SOLUTIONS:  Since lower layer library does not declare
frqqd_config_t in new platform, top layer application
needs to declare new structure with members needed from frqqd_config_t.
Requirement is to use same set of files for both platforms, old and new.
One possibility is use compile time platform flags as follows:


typedef struct
{
   /* Initialization Function */
   void (*fc_init) (alg_work_t *work, alg_cfg_t *config);

   /* Main Function */
   void (*fc_main) (alg_work_t *work, alg_cfg_t *config);
    
   #if (old_platform)

     /* This structure is used to read the raw frequency/direction from the
hardware */
     frqqd_config_t input_config;
   
   #else
 
     app_frqq_config_t *input_config;
  
   #endif


   /* some member */
   int member1;

} spdwdir_config_t;


By the way, instead of pointer to app_frqq_config_t, why not just say the
following:

app_frqq_config_t input;


What are other solutions? what's the best solution.
	   
					
---------------------------------------		
Posted through http://www.EmbeddedRelated.com
On 5/24/2011 9:01 AM, janii wrote:
> Following structure declared by lower layer library is as follows: It is > instantiated by top > layer application. A pointer to this structure is passed to lower layer > library functions. > > typedef struct { > void (*fc_init) (alg_work_t *work, alg_cfg_t *config); > void (*fc_main) (alg_work_t *work, alg_cfg_t *config); > frqqd_config_t input_config; > int member1; > } spdwdir_config_t; > > typedef struct { > int tpu; > int primary_channel; > int secondary_channel; > int edge; > int tcr; > int tpu_priority; > int debounce_time; > unsigned int max_period; > unsigned int min_period; > unsigned int timeout; > } frqqd_config_t; > > In new platform, structure frqqd_config_t does not exist.
What do you mean, "does not exist"? Shirley, *you* decide what does and does NOT exist... (or, is this part of a commercial API you are licensing?)
> Top layer application still needs to pass > following members from this structure to lower layer library functions: > > typed struct { > void * primary_channel > int debounce_time; > unsigned int max_period; > unsigned int min_period; > unsigned int timeout; > } app_frqqd_config_t;
Why can't you wedge those into the frqqd_config_t struct -- leaving unused members "undefined" (or, init to some arbitrary constant) and change data types accordingly for, e.g., the differences in "primary_channel"? Presumably, you are also rewriting the code that *uses* these structs/types. So, do you need to support *both* in your code base? Or, can you just fork your development off at this point and abandon the old API?
> POSSIBLE SOLUTIONS: Since lower layer library does not declare > frqqd_config_t in new platform, top layer application > needs to declare new structure with members needed from frqqd_config_t. > Requirement is to use same set of files for both platforms, old and new. > One possibility is use compile time platform flags as follows: > > typedef struct { > void (*fc_init) (alg_work_t *work, alg_cfg_t *config); > void (*fc_main) (alg_work_t *work, alg_cfg_t *config); > > #if (old_platform) > frqqd_config_t input_config; > #else > app_frqq_config_t *input_config; > #endif > > int member1; > } spdwdir_config_t; > > By the way, instead of pointer to app_frqq_config_t, why not just say the > following: > > app_frqq_config_t input;
Why are you using a pointer to a struct (type) in one case and the struct itself in the other? What makes the most *sense* to the design of the application -- does the frqqd_config_t belong *in* the spdwdir_config_t or should the spdwdir_config_t *reference* it instead?
> What are other solutions? what's the best solution.
The exact nature of your problem is unclear. Why not ask whomever changed the API *why* the changes were made and look at how that *intuitively* reflects on the design of the code. E.g., if they are intended to be compatible -- or not!
>On 5/24/2011 9:01 AM, janii wrote: >> Following structure declared by lower layer library is as follows: It
is
>> instantiated by top >> layer application. A pointer to this structure is passed to lower
layer
>> library functions. >> >> typedef struct { >> void (*fc_init) (alg_work_t *work, alg_cfg_t *config); >> void (*fc_main) (alg_work_t *work, alg_cfg_t *config); >> frqqd_config_t input_config; >> int member1; >> } spdwdir_config_t; >> >> typedef struct { >> int tpu; >> int primary_channel; >> int secondary_channel; >> int edge; >> int tcr; >> int tpu_priority; >> int debounce_time; >> unsigned int max_period; >> unsigned int min_period; >> unsigned int timeout; >> } frqqd_config_t; >> >> In new platform, structure frqqd_config_t does not exist. > >What do you mean, "does not exist"? Shirley, *you* decide what >does and does NOT exist... (or, is this part of a commercial >API you are licensing?) > >> Top layer application still needs to pass >> following members from this structure to lower layer library functions: >> >> typed struct { >> void * primary_channel >> int debounce_time; >> unsigned int max_period; >> unsigned int min_period; >> unsigned int timeout; >> } app_frqqd_config_t; > >Why can't you wedge those into the frqqd_config_t struct -- leaving >unused members "undefined" (or, init to some arbitrary constant) >and change data types accordingly for, e.g., the differences in >"primary_channel"? > >Presumably, you are also rewriting the code that *uses* these >structs/types. So, do you need to support *both* in your >code base? Or, can you just fork your development off at >this point and abandon the old API? > >> POSSIBLE SOLUTIONS: Since lower layer library does not declare >> frqqd_config_t in new platform, top layer application >> needs to declare new structure with members needed from frqqd_config_t. >> Requirement is to use same set of files for both platforms, old and
new.
>> One possibility is use compile time platform flags as follows: >> >> typedef struct { >> void (*fc_init) (alg_work_t *work, alg_cfg_t *config); >> void (*fc_main) (alg_work_t *work, alg_cfg_t *config); >> >> #if (old_platform) >> frqqd_config_t input_config; >> #else >> app_frqq_config_t *input_config; >> #endif >> >> int member1; >> } spdwdir_config_t; >> >> By the way, instead of pointer to app_frqq_config_t, why not just say
the
>> following: >> >> app_frqq_config_t input; > >Why are you using a pointer to a struct (type) in one case and the >struct itself in the other? What makes the most *sense* to the >design of the application -- does the frqqd_config_t belong *in* >the spdwdir_config_t or should the spdwdir_config_t *reference* >it instead? > >> What are other solutions? what's the best solution. > >The exact nature of your problem is unclear. Why not ask >whomever changed the API *why* the changes were made and >look at how that *intuitively* reflects on the design of the >code. E.g., if they are intended to be compatible -- or not! >
>> What do you mean, "does not exist"?
structure frqqd_config_t doesn't exist in new platform because it is owned by lower layer library and they decided to remove it from the new platform. Their thought is that application may not need to provide frqqd configuration. Default frqqd configuration will be provided by the lower layer library. If default frqqd configuration doesn't work for the application, they can change it by calling APIs. This is not part of commercial API we are licensing.
>> (or, init to some arbitrary constant) >> and change data types accordingly for, e.g., the differences in >> "primary_channel"?
pointer structure spdwdir_config_t is passed to lower layer library. If I init parameters, how will they get passed to lower layer library.
>> Why can't you wedge those into the frqqd_config_t
It doesn't exist in new platform.
>> So, do you need to support *both* in your >> code base?
Yes, both need to be supported in our code base.
>> Why are you using a pointer to a struct (type) in one case and the >> struct itself in the other?
struct frqqd_config_t exists in old platform. For new platfrom, I'm proposing pointer to new struct app_frqqd_config_t. Or it can be struct itself. I asked which is preferred?
>> does the frqqd_config_t belong *in* >> the spdwdir_config_t
Yes. --------------------------------------- Posted through http://www.EmbeddedRelated.com
On 5/24/2011 1:30 PM, janii wrote:

[ much elided as I couldn't make heads nor tails of its value]

>>> What do you mean, "does not exist"? > structure frqqd_config_t doesn't exist in new platform because it is owned > by > lower layer library and they decided to remove it from the new platform.
Anything not present in the API to that level *can't* be present in the gazintas and cumzoutas of your higher level. Period. That's the whole point of the interface contract. You *might* choose to implement a frqqd_config_t (or similar) in an upper layer -- if it has some value to *that* layer. You just can't pass it across that interface.
> Their thought is that application may not need to provide frqqd > configuration. Default frqqd configuration will be provided by the lower > layer library. If
OK. And, how does the upper layer *inspect* the "current state" of that struct (without giving it a name)?
> default frqqd configuration doesn't work for the application, they can > change it by calling APIs.
So, you have: error_t get_tpu(&int) error_t set_tpu(int) error_t get_primary_channel(&int) error_t set_primary_channel(int) etc.? I.e., otherwise, how can you examine the current state of the struct in order to decide how you would *like* to change it?
> This is not part of commercial API we are licensing. > >>> (or, init to some arbitrary constant) >>> and change data types accordingly for, e.g., the differences in >>> "primary_channel"? > pointer structure spdwdir_config_t is passed to lower layer library. If I > init parameters, how will they get passed to lower layer library.
If you have no control over the interface, then my suggestion doesn't apply -- you can't deviate from That What Hath Been Written.
>>> Why can't you wedge those into the frqqd_config_t > It doesn't exist in new platform. > >>> So, do you need to support *both* in your >>> code base? > Yes, both need to be supported in our code base. > >>> Why are you using a pointer to a struct (type) in one case and the >>> struct itself in the other? > struct frqqd_config_t exists in old platform. For new platfrom, I'm > proposing pointer to new struct app_frqqd_config_t. Or it can be struct > itself. I asked which is preferred?
Think of what the *data* suggests. Does the object make sense as an object in its own right? Could/would it stand on its own? Is it likely to be *shared* (referenced) by two or more things? E.g., if there are 4 children in your family and you had to describe each of them, would you say: typedef struct { char name[BUFSIZ]; int age; char mothers_name[BUFSIZ]; char fathers_name[BUFSIZ]; ... } child_t; or, would you say: typedef struct { char name[BUFSIZ]; int age; parent_t *mother; parent_t *father; ... } child_t; typedef struct { char name[BUFSIZ]; ... } parent_t; Note that the data model can suggest one, the other or even *both* of these approaches. And, whichever you choose has associated consequences.
>>> does the frqqd_config_t belong *in* >>> the spdwdir_config_t > Yes.