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