SOM supports methods whose final argument is a va_list. A va_list is a data type whose representation depends on the operating-system platform. To aid construction of portable code, SOM supports a platform-neutral API for building and manipulating va_lists. Use of this API is recommended on all platforms because it is compliant with the ANSI C standard and because of its portability.
Note: Initially support for va_list functions is available only for the PowerPC platform. With the release of SOM 3.0 however, support is extended to the PC platform.
A function to create a va_list is not provided. Instead, users declare local variables of type somVaBuf and va_list.
The following sequence of calls is used to create and destroy a va_list:
Creates a SOM buffer for variable arguments from which the va_list will be built.
Adds an argument to the SOM buffer for variable arguments.
Copies the va_list from the SOM buffer.
Releases the SOM buffer and its associated va_list.
Modifies the first scalar value on the va_list without other side effects.
Gets the first scalar value from the va_list without other side effects.
Detailed information on these functions is provided in the System Object Model Programming Reference.
Examples of va_list usage
The following code segments pass a va_list to the somDispatch method by using the SOMobjects functions that build the va_list.
The somDispatch method (introduced by SOMObject) is a particularly useful method whose final argument is a va_list. As explained in the System Object Model Programming Reference, somDispatch can be used to invoke some other method (called the "dispatched" method) on an object when usage bindings for the dispatched method are not available or when the method to be dispatched is not known until run time. The va_list argument for somDispatch holds the arguments that will be passed to the dispatched method, including the target object for the dispatched method.
For C:
#include <somobj.h>void f1(SOMObject obj, Environment *ev) { char *msg; va_list start_val; somVaBuf vb; char *msg1 = "Good Morning"; vb = (somVaBuf)somVaBuf_create(NULL, 0); somVaBuf_add(vb, (char *)&obj, tk_pointer); /* target for _set_msg */ somVaBuf_add(vb, (char *)&ev, tk_pointer); /* next argument */ somVaBuf_add(vb, (char *)&msg1, tk_pointer); /* final argument */ somVaBuf_get_valist(vb, &start_val); /* dispatch _set_msg on object */ SOMObject_somDispatch( obj, /* target for somDispatch */ 0, /* says ignore dispatched method result */ somIdFromString("_set_msg"), /* the somId for _set_msg */ start_val); /* target and args for _set_msg */ /* dispatch _get_msg on obj: */ /* Get a fresh copy of the va_list */ somVaBuf_get_valist(vb, &start_val); SOMObject_somDispatch( obj, (somToken *)&msg, /* address to store dispatched result */ somIdFromString("_get_msg"), start_val); /* target and arguments for _get_msg */ printf("%s\n",msg); somVaBuf_destroy(vb); }For C++:
#include <somobj.h> void f1(SOMObject obj, Environment *ev) { char *msg; va_list start_val; somVaBuf vb; char *msg1 = "Good Morning"; vb = (somVaBuf)somVaBuf_create(NULL, 0); somVaBuf_add(vb, (char *)&obj, tk_pointer); /* target for _set_msg */ somVaBuf_add(vb, (char *)&ev, tk_pointer); /* next argument */ somVaBuf_add(vb, (char *)&msg1, tk_pointer); /* final argument */ somVaBuf_get_valist(vb, &start_val); /* dispatch _set_msg on object */ obj->SOMObject_somDispatch( 0, /* says ignore dispatched method result */ somIdFromString("_set_msg"), /* the somId for _set_msg */ start_val); /* target and args for _set_msg */ /* dispatch _get_msg on obj: */ /* Get a fresh copy of the va_list */ somVaBuf_get_valist(vb, &start_val); obj->SOMObject_somDispatch( (somToken *)&msg, /* address to store dispatched result */ somIdFromString("_get_msg"), start_val); /* target and arguments for _get_msg */ printf("%s\n",msg); somVaBuf_destroy(vb); }
As a convenience, methods whose final argument is a va_list can be invoked from C and C++ by using the short form of method invocation and specifying a variable number of arguments in place of the va_list. That is, beginning at the syntax position where the va_list argument is expected, SOMobjects interprets all subsequent arguments as being the components of the va_list. This is illustrated below, using the somDispatch method.
As an example of using the variable-argument interface to somDispatch, the following code segments illustrate how an example of attribute access (in the topic "Accessing attributes") could be recoded to operate without usage bindings for the "Hello" class. These code segments are expressed as functions that accept an argument of type SOMObject under the assumption that bindings for "Hello" are not available. (This requires usage bindings for SOMObject, which are also required for calling somDispatch.)
For C:
#include <somobj.h> void f1(SOMObject obj, Environment *ev) { char *msg; /* dispatch _set_msg on obj: */ _somDispatch( obj, /* the target for somDispatch */ 0, /* says ignore the dispatched method result */ somIdFromString("_set_msg"), /* the somId for _set_msg */ obj, /* the target for _set_msg */ ev, /* the other arguments for _set_msg */ "Good Morning"); /* dispatch _get_msg on obj: */ _somDispatch( obj, (somToken *)&msg, /* address to hold dispatched method result */ somIdFromString("_get_msg"), obj, /* the target for _get_msg */ ev); /* the other argument for _get_msg */ printf("%s\n", msg); }
For C++:
#include <somobj.h> void f1(SOMObject obj, Environment *ev) { char *msg; /* dispatch _set_msg on obj: */ obj->somDispatch( 0, /* says ignore the dispatched method result */ somIdFromString("_set_msg"), /* dispatched method id */ obj, /* the target for _set_msg */ ev, /* the other arguments for _set_msg */ "Good Morning"); /* dispatch _get_msg on obj: */ obj->somDispatch( (somToken *)&msg, /* address to store dispatched result */ somIdFromString("_get_msg"), obj, ev); printf("%s\n", msg); }
C programmers must be aware that the "short form" of the invocation macro that is used above to pass a variable number of arguments to a va_list method is only available in the absence of ambiguity. The long-form macro (which is always available) requires an explicit va_list argument. (See "Short form vs long form" under "Making typical method calls" earlier in this chapter.)