Creating an interface to variables

Hi:

I have an embedded system, platform: TI TMS320F2812 32-bit integer DSP.

A module (.c file) contains external (to the funcs in that module) variables which are used to affect the operation of the program (other modules). These variables are only read by other parts of the program, but are to be set by a user interface which consists of an RS-232 terminal command line interface. The command parser for this interface responds to commands to get or set the variables.

In the interest of good programming practice I desired to have the parser know as little as possible about the variables. It doesn't set or read them directly, but through an interface. The parser contains a table of pointers to variable attribute structures. Each pointer is associated with a packed string id for the variable. When a match is made, it passes the pointer (and perhaps a set value) to the variable attribute struct to the get or set accessor function for the variable.

Here is the interface to the variables. Note, that it only needs to be general up to the point of handling the machine's native int16 and int32 access sizes.

If you have any better ideas or criticisms, please let me know. I am not fully happy with the use of void * . I tried to use a union in two different ways, but not successfully.

Thanks:

-------------------------------------------------------------------- // use-vars.h // header for module with variables to be interfaced:

// a var may be signed or unsigned (u)int16 or (u)int32 extern uint16 Var1; extern int32 Var2;

-------------------------------------------------------------------- // vars.h // header for module which implements interface:

#include "use-vars.h"

#define VAR_RW_OK 0 #define VAR_RW_ERR_RANGE -1 #define VAR_RW_ERR_TYPE -2

/* This defines which type is used at the interface level to pass values to/from variable read/write access functions, and to define the bounds. This must be the largest type for which any variable might need to be accessed: */

typedef int32 VarRW_t;

struct VarAttribs { void *vptr; // pointer to variable -- tried union unsuccessfully int vsize; // sizeof() variable VarRW_t vmin; // lower bound VarRW_t vmax; // upper bound };

typedef struct VarAttribs VarAttribs_t;

int var_set(VarAttribs_t *, VarRW_t); VarRW_t var_get(VarAttribs_t *);

extern VarAttribs_t Var1_attr; extern VarAttribs_t Var2_attr;

-------------------------------------------------------------------- // vars.c

#include "use-vars.h" #include "vars.h"

// Here we define the variable attributes: VarAttribs_t Var1_attr = {&Var1, sizeof(Var1), 1, 10}; VarAttribs_t Var1_attr = {&Var2, sizeof(Var2), -50000, 50000};

// Functions for accessing variables (only set shown):

int var_set(VarAttribs_t *vi, VarRW_t val) { if ( val < vi->vmin || val > vi->vmax ) return(VAR_RW_ERR_RANGE); else { if ( vi->vsize == sizeof(int16) ) *(int16 *)vi->vptr = (int16) val; else if ( vi->vsize == sizeof(int32) ) *(int32 *)vi->vptr = (int32) val; else return (VAR_RW_ERR_TYPE); } return(VAR_RW_OK); }

---------------------------------------------------------------------- // parse.c // module which accesses the variables

#include "vars.h"

/* if a command is parsed which provides the value v to set the variable identified "Var1", and the table lookup has returned a pointer to the Var1_attr structure, then: */

if ( var_set(&Var1_attr, v) != VAR_RW_OK ) deal_with_badness(); // else continue...

--
Good day!

________________________________________
 Click to see the full signature
Reply to
Chris Carlen
Loading thread data ...

[...]

I think you need more than the size to distinguish between different types of variables. Even with just the types you have it looks dodgy (signed vs. unsigned), although you might get away with it on your platform. And I think you will likely need other types in the future that can't be distinguished using the sizeof.

I too have found this to be a thorny problem and would also be interested in other approaches. I usually end up using an enumeration to label the type in the "attributes" structure.

typedef enum { BOOL, TRIPLE, QUAD, QUINT, STRING, INT, LONG, TIME8, LINK, COMMAND, CONFIRM_COMMAND } SETTING_TYPE;

Then do a switch by setting type.

Over the years I seem to have embellished this stuff, to the point where I now have a text file (a "resource" file) containing all the variable definitions, defaults, descriptive text and menu structure. This gets processed by an awk script to programmatically generate various C header files.

--

John Devereux
Reply to
John Devereux

Yeah, I seem to be moving in this direction, having thought about it further.

Thanks for the input!

--
Good day!

________________________________________
 Click to see the full signature
Reply to
Chris Carlen

Maybe look at how SNMP descriptors work, as this is basically the same problem.

Reply to
Clifford Heath

for quick & dirty, you could associate a scanf/printf string with each variable.

--
	mac the naïf
Reply to
Alex Colvin

It would be interesting to see what problems you had here. A union of the four pointer types should be pretty straight forward.

Since you say your variables could be signed or unsigned, it is possible the vmax may not be able to hold the desired value when vptr points to a uint32.

Similarly, the may be numerous valid uint32 values this function cannot return. Since you don't show var_get, I wonder how you intend it to indicate failure. Unless your variables have limited range, any value returned would be valid int32 value. (One method would be to pass the address of the address of the target variable to receive the value as a second argument and have the return value be a status indicator like it is in var_set. The function could then update the target variable directly with the value from the source variable.)

vars.h includes use-vars.h explicitly so you don't need to include it here. It is not a problem now since use-vars.h only declares a few external objects but you could run into problems as your project develops. You may want to add include guards to both headers.

Again, how to deal with uint32 values greater than the max int32 value.

How do you know it is an int16 and not a uint16? You really need a method to identify the type properly (such as an enum member of VarAttribs_t).

Remove del for email

Reply to
Barry Schwarz

To declare, yes, but ...

(I assume that was meant to be Var2_attr!)

... initializing it like this would work for at most one type; otherwise you need C99 designated initializers: VarAttribs_t Var1_attr = { {.uint16ptr = &Var1}, -3, 42};

- formerly david.thompson1 || achar(64) || worldnet.att.net

Reply to
David Thompson

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.