How to use
Original implementation
The original implementation uses a variadic macro defined in PXROS-HR API.
#include <stdarg.h>
int myHandler0()
{
return 0; /* indicate success */
}
int myHandler1(int arg1)
{
return 0; /* indicate success */
}
int myHandler2(int arg1, int arg2)
{
return 0; /* indicate success */
}
int myHandlerX(int arg_cnt, ...)
{
va_list list;
va_start(list, arg_cnt);
int sum = 0;
int *out_arg = va_arg(list, int *);
for (int i = 0; i < (arg_cnt - 1); i++)
sum += va_arg(list, int);
va_end(list);
*out_arg = sum;
return 0; /* indicate success */
}
/* The _PxHndcall() expects at least three arguments:
* 1) the function/handler to be called
* 2) the Task ID (required even if not used)
* 3) size of the arguments (required even if not used)
* There can be any number of additional arguments that
* will be passed to the handler. */
#define UNUSED_TID 0 /* TASK ID - argument not used */
#define UNUSED_VARSIZE 0 /* VARIABLE SIZE - argument not used */
int arg1, arg2, arg3, arg4, arg5, sum; /* Handler's arguments */
PxArg_t retval; /* Handler's return value. For simplicity not checked here. */
/* Calling myHandler0(void), i.e. handler that does not take arguments */
retval = _PxHndcall(myHandler0, UNUSED_TID, UNUSED_VARSIZE);
/* Calling myHandler1(int), i.e. handler accepting one argument */
retval = _PxHndcall(myHandler1, UNUSED_TID, UNUSED_VARSIZE, arg1);
/* Calling myHandler2(int, int), i.e. handler accepting two arguments */
retval = _PxHndcall(myHandler2, UNUSED_TID, UNUSED_VARSIZE, arg1, arg2);
/* Calling myHandlerX(int, ...), i.e. handler accepting any number of arguments */
retval = _PxHndcall(myHandlerX, UNUSED_TID, UNUSED_VARSIZE,
6 /* nr. of args */, &sum, arg1, arg2, arg3, arg4, arg5);
New implementation
PxHndcallVA
Pass a variadic function as a handler
int _PxHndcallVA(int (*hnd)(va_list), ...);
Parameters:
-
hnd — function to execute with supervisor privileges
-
… — argument list of the variadic handler function
Return value:
-
Return value of the function executed in supervisor mode
Description:
The function hnd
will be called with supervisor privileges with the pointer to the arguments passed on the stack as its argument.
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* The handler function must use the C calling convention */
int handler_function(va_list ap);
#ifdef __cplusplus
}
#endif /* __cplusplus */
/* A sample handler function using 3 arguments */
int handler_function(va_list ap)
{
int arg1 = va_arg(ap, int);
int arg2 = va_arg(ap, int);
int arg3 = va_arg(ap, int);
...
return 0; /* indicate success */
}
/* A task function */
void task_function(PxTask_t myID, PxMbx_t myMailbox, PxEvents_t myActEvents)
{
...
/* Call the handler function with 3 arguments */
_PxHndcallVA(handler_function, arg1, arg2, arg3);
...
}
PxHndcallPTR
Pass a function with pointer argument as a handler
int _PxHndcallPTR(int (*hnd)(void *), void *arg);
Parameters:
-
hnd — function to execute with supervisor privileges
-
arg — argument of the handler function (pointer)
Return value:
-
Return value of the function executed in supervisor mode
Description:
The function hnd
will be called in supervisor mode with arg
as its argument.
/* Structure to pass several values to the handler function */
typedef struct {
int arg1;
int arg2;
int arg3;
} hndarg_t;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* The handler function must use the C calling convention */
int handler_function(hndarg_t *p);
#ifdef __cplusplus
}
#endif /* __cplusplus */
/* A sample handler function expecting pointer to a structure */
int handler_function(hndarg_t *p)
{
int arg1 = p->arg1; /* Readning input value from calling task */
p->arg2 = OUTPUT_VALUE; /* Passing output value to calling task */
return 0; /* indicate success */
}
/* A task function */
void task_function(PxTask_t myID, PxMbx_t myMailbox, PxEvents_t myActEvents)
{
...
/* Initialize the argument structure */
hndarg_t arg;
arg.arg1 = INPUT_VALUE;
/* Call the handler function with a pointer to the argument structure */
_PxHndcallPTR(handler_function, &arg);
...
}