10-30-2014 07:25 AM
I have a variable argument function:
int SetAttribute(object obj, int attrib, ...);
I want to check the type a user puts to the variable list at runtime. CVI itself can check the type put into SetCtrlAttribute(int panel, int ctrl, ..). Is it possible to check the type within a va_list at runtime?
Thanks in advance.
10-31-2014 07:28 AM
Hi,
yould you please post more details about what you want to do? I do not really understand your question. Do you want to specify a data type at run-time, because at compliation time this is not known?
Furthermore, where does the SetAttribute function comes from? It is not a standard CVI function I believe,
Best Regards, Fabian
10-31-2014 08:05 AM
This is standard CVI:
int CVIFUNC_C SetCtrlAttribute(int panel, int control, int attribute, ...);
any attributes entered into SetCtrlAttribute() will be type checked by CVI. If you put a wrong type to the attribute value (the "..." parameter) you will get a runtime error message.
This is NOT CVI:
typedef struct anonym* Object;
int Object_SetAttribute(Object mvalue, int attrib, ...)
{
va_list args;
va_start(args,attrib);
// This is actualy a cast to int but you can not be sure if the parameter entered in "..." is realy int.
// CVI can type check here. With RTTI (Runtime type checking) one can check if the attribute is realy of type int.
// If CVI does it internaly, can a CVI user does it too?
int x = va_arg(args,int);
va_end(args);
return x;
}
The compiler will not complain if you do:
Object_SetAttribute(object, 123,"ABC");
I would like to check the type of a parameter from a variable parameter list before I extract the parameter from the list. This is very helpful to avoid bugs and saves time when debugging.
I hope this explains my problem.
11-10-2014 04:09 AM
Hi,
the CVI Function works in the following way. see help documentation:
http://zone.ni.com/reference/en-XX/help/370051T-01/cvi/uiref/cvigetctrlattribute/
it is a void pointer.
you can also created a variable argument list:
http://www.ni.com/example/29450/en/
the only way how to do it would be via such a pointer and realize it on the same way
Best Regards, Fabian
11-10-2014 04:58 AM
I remember to have found an example which I can't locate at the moment that passes both the variable value and type to the variable-argument function. The structure is as follows:
// Typo of parameters passed to the function ("stdarg.h")
#define INTPRM 1 // Integer
#define DBLPRM 2 // Double
#define CHRPRM 3 // Char
#define STRPRM 4 // Structure
typedef struct {
double Dprm;
int Iprm;
char Cprm[16];
} dummy;
void VarParmFunc (int *parms, ...);
// Button callback which uses the variable-argument function
int CVICALLBACK varFunc (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
int cnt = 0;
int Iprm;
double Dprm;
char Cprm[16];
dummy *dd = NULL;
if (event != EVENT_COMMIT) return 0;
// Read values and fill-in type array
GetCtrlVal (panel, PANEL_parm1, &Dprm);
parms[cnt++] = DBLPRM;
GetCtrlVal (panel, PANEL_parm2, &Iprm);
parms[cnt++] = INTPRM;
GetCtrlVal (panel, PANEL_parm3, Cprm);
parms[cnt++] = CHRPRM;
dd = malloc (sizeof (dummy));
GetCtrlVal (panel, PANEL_Field1, &dd->Dprm);
GetCtrlVal (panel, PANEL_Field2, &dd->Iprm);
GetCtrlVal (panel, PANEL_Field3, dd->Cprm);
parms[cnt++] = STRPRM;
parms[cnt++] = 0;
VarParmFunc (parms, Dprm, Iprm, Cprm, dd);
if (dd) free (dd);
return 0;
}
// Variable-arguments function
void VarParmFunc (int *parms, ...)
// This simply echos received parameters
{
int cnt = 0;
char type, msg[256];
dummy *dd;
va_list ap;
if (!parms) goto Exit;
// Initialize variable-argument list handling
va_start (ap, parms);
strcpy (msg, "Received parms:\n");
// List parameters
while ((type = *parms++) != 0) {
switch (type) {
case INTPRM:
sprintf (msg, "%s\n Integer: %d", msg, va_arg (ap, int));
cnt++;
break;
case DBLPRM:
sprintf (msg, "%s\n Double %.2f", msg, va_arg (ap, double));
cnt++;
break;
case CHRPRM:
sprintf (msg, "%s\n String: %s", msg, va_arg (ap, char *));
cnt++;
break;
case STRPRM:
dd = va_arg (ap, dummy *);
sprintf (msg, "%s\n Struct:\n Double: %.2f\n Integer: %d\n String: %s", msg,
dd->Dprm, dd->Iprm, dd->Cprm);
cnt++;
break;
}
}
ResetTextBox (mainH, PANEL_res, msg);
Exit:
sprintf (msg, "%d parameters received", cnt);
MessagePopup ("Variable params", msg);
Error:
// End variable arguments handling
va_end (ap);
return;
}
11-10-2014 05:00 AM
An alternative can be to use variants instead of simple variables: as you may know, variants can store different types of data and can be queried for the type store in them by means of CA_VariantGetType () function. This can simplify type checking inside your function, at the cost of a considerably more complex data handling.
11-10-2014 05:40 AM
The link above contains an ' ':
http://zone.ni.com/reference/en-XX/help/370051T-01/cvi/uiref/cvigetctrlattribute/
The help page does not tell anything about RTTI.
I copied the SetCtrlAttribute() function from the header of CVI2013. There is no void*. See userint.h.
And you can try to use a wrong type to the attribute setter of a control and you will get a runtime error message.
Yes and I did write an example already for using va_list. Another example dosen't help.
11-10-2014 05:51 AM
Thanks Roberto for your Tips. I was thinking on that already but I can not ask my users to striktly insert a correct type into the parameter list.
The probability of using a wrong type will not change with that aproach. I have to implement it without RTTI.
May be NI will publish a solution to that once. The best solution would be a RTTI implementation to the compiler. I don't know the effort to spend in devloping RTTI for CVI but that would improve stability to CVI generated products.
Regards
Andrej