Common WWSAPI errors: A NULL WS_STRUCT_DESCRIPTION was specified.

Common WWSAPI errors: A NULL WS_STRUCT_DESCRIPTION was specified.

When you use WsUtil to generate stub code and then work with the generated structures, you may get E_INVALIDARG when making the call to the service and, with WWSAPI tracing turned on, see the error message “A NULL WS_STRUCT_DESCRIPTION was specified.”.

WS_STRUCT_DESCRIPTION is one of the WWSAPI serialization structures and describes how a structure should be serialized into XML and deserialized from XML. When you use WsUtil to generate the stub code, lots of complex structures will be generated, including WS_STRUCT_DESCRIPTION. You’ll need to make sure that the structures are initialized properly. By default, if you use a structure that has either a base structure or derived structure(s), you should use a generated function to initialize it. For example, say the schema in the WSDL defines a type Location that has two derived types UserLocation and GeocodeLocation, WsUtil will generate the Location type like the following:

#if !defined(WS_CPLUSPLUS)

typedefstruct Location

{

conststruct _WS_STRUCT_DESCRIPTION* _type;

double Altitude;

double Latitude;

double Longitude;

} Location;

void WINAPI Location_Init(Location*);

struct UserLocation* WINAPI Location_AsUserLocation(Location*);

struct GeocodeLocation* WINAPI Location_AsGeocodeLocation(Location*);

#endif

Notice the function Location_Init after the structure. In order to properly initialize a Location structure, you need to call the Location_Init function like this:

Location location = {NULL, 0, latitude, longitude};

Location_Init(&location);

When you get the E_INVALIDARG with the error message I mentioned above, it’s because you forgot to call the *_Init function, which will set the WS_STRUCT_DESCRIPTION structure (the location._type field in this example). The Location_Init is generated like the following:

The *_Init functions (and the _type field) won’t be generated for types that don’t have base type or derived types. When you are consuming a service without knowing the details of the server type definitions, it’s always a good idea to open up the generated header file to see if *_Init functions are generated for the structures you use.

Please note that this is the default behavior. If you define a preprocessor WS_CPLUSPLUS, the requirement is different. I’ll discuss that in a later post.