Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
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)
typedef struct Location
{
const struct _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:
#if !defined(WS_CPLUSPLUS)
void WINAPI Location_Init(Location* _Location)
{
((Location*)_Location)->_type =
(WS_STRUCT_DESCRIPTION*)&dev_virtualearth_net_webservices_v1_common1_xsd.globalTypes.Location;
}
#endif
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.
For further reading on WsUtil’s support of XML schema, please go to https://msdn.microsoft.com/en-us/library/dd815313(VS.85).aspx.