This is preliminary documentation and subject to change.
To comment on this topic, please send us email at ngwssdk@microsoft.com. Thanks!
In/Out Marshaling
Every parameter can optionally have associated with it a setting for it’s IN and OUT attributes. These settings describe the direction that data is intended to flow between the caller and the callee but they have no bearing on the level of indirection used by the parameters. The runtime marshaling infrastructure uses the IN/OUT attributes to decide how each parameter should be marshaled between managed and unmanaged code.
- IN parameters are initialized by the caller and changes by the callee are not reflected in the caller’s view.
- OUT parameters are considered not to be initialized by the caller and changes made by the callee are reflected in the caller’s view.
- IN/OUT parameters are initialized by the caller and changes made by the callee are reflected in the callers view.
In the absence of explicit IN/OUT settings, the runtime assumes that all by-reference parameters are passed IN/OUT and that all other non by-reference parameters are IN. The only exception is the StringBuilder class, which is also always assumed to be IN/OUT.
Other points concerning marhaling direction:
- Value types and base data types are, by default, In (in fact marking them as Out or In/Out is an error).
- NGWS classes are, by default, In. As described above classes can be marshaled as COM interfaces or as pointers to structures. When classes are marshaled as a COM Interface Out and In/Out are inapplicable and therefore illegal. When classes are marshaled as a pointer to a structure they can be marked as Out and In/Out. There are two interesting cases of marshaling as a pointer to a structure (see the section above on Formatted Types for an explanation):
- Formatted, Isomorphic – Regardless of the setting of the In and Out attributes, a pointer to the actual class contents is passed and therefore it is as if the parameter had been marked In/Out.
- Formatted, Non-isomorphic – When a non-isomorphic class is marshaled as a pointer to a structure the callee receives a pointer to a copy of the structure. If the In attribute is set, this copy is initialized (marshaling as necessary) with the instances state. If the Out attribute is set the state is copied (again marshaling as necessary) back in to the instance on return. If both In/Out is set, both copies occur.
There are a few classes which are exceptions to the above rules.
- String – Strings can only be marshaled in. When Strings are marshaled as LPWStrs (or LPTStrS on a Unicode platform) they are marshalled as Formatted, Isomorphic classes but should not be modified by the callee as strings are intended to be immutable in the Runtime.
- StringBuilder – StringBuilders default to In/Out rather than In. This reflects their common usage in marshaling.
- Function Pointer – Bi-directional Need to cover lifetime issues
- By-ref parameters default are, by default In/Out, but can be marked as In or Out as well.