A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://learn.microsoft.com/en-us/dotnet/framework/interop/default-marshalling-for-objects below:

Default Marshalling for Objects - .NET Framework

Parameters and fields typed as System.Object can be exposed to unmanaged code as one of the following types:

Only COM interop supports marshalling for object types. The default behavior is to marshal objects to COM variants. These rules apply only to the type Object and do not apply to strongly typed objects that derive from the Object class.

Marshalling Options

The following table shows the marshalling options for the Object data type. The MarshalAsAttribute attribute provides several UnmanagedType enumeration values to marshal objects.

Enumeration type Description of unmanaged format UnmanagedType.Struct

(default for parameters)

A COM-style variant. UnmanagedType.Interface An IDispatch interface, if possible; otherwise, an IUnknown interface. UnmanagedType.IUnknown

(default for fields)

An IUnknown interface. UnmanagedType.IDispatch An IDispatch interface.

The following example shows the managed interface definition for MarshalObject.

Interface MarshalObject
   Sub SetVariant(o As Object)
   Sub SetVariantRef(ByRef o As Object)
   Function GetVariant() As Object

   Sub SetIDispatch( <MarshalAs(UnmanagedType.IDispatch)> o As Object)
   Sub SetIDispatchRef(ByRef <MarshalAs(UnmanagedType.IDispatch)> o _
      As Object)
   Function GetIDispatch() As <MarshalAs(UnmanagedType.IDispatch)> Object
   Sub SetIUnknown( <MarshalAs(UnmanagedType.IUnknown)> o As Object)
   Sub SetIUnknownRef(ByRef <MarshalAs(UnmanagedType.IUnknown)> o _
      As Object)
   Function GetIUnknown() As <MarshalAs(UnmanagedType.IUnknown)> Object
End Interface
interface MarshalObject {
   void SetVariant(Object o);
   void SetVariantRef(ref Object o);
   Object GetVariant();

   void SetIDispatch ([MarshalAs(UnmanagedType.IDispatch)]Object o);
   void SetIDispatchRef([MarshalAs(UnmanagedType.IDispatch)]ref Object o);
   [MarshalAs(UnmanagedType.IDispatch)] Object GetIDispatch();
   void SetIUnknown ([MarshalAs(UnmanagedType.IUnknown)]Object o);
   void SetIUnknownRef([MarshalAs(UnmanagedType.IUnknown)]ref Object o);
   [MarshalAs(UnmanagedType.IUnknown)] Object GetIUnknown();
}

The following code exports the MarshalObject interface to a type library.

interface MarshalObject {
   HRESULT SetVariant([in] VARIANT o);
   HRESULT SetVariantRef([in,out] VARIANT *o);
   HRESULT GetVariant([out,retval] VARIANT *o)
   HRESULT SetIDispatch([in] IDispatch *o);
   HRESULT SetIDispatchRef([in,out] IDispatch **o);
   HRESULT GetIDispatch([out,retval] IDispatch **o)
   HRESULT SetIUnknown([in] IUnknown *o);
   HRESULT SetIUnknownRef([in,out] IUnknown **o);
   HRESULT GetIUnknown([out,retval] IUnknown **o)
}

Note

The interop marshaller automatically frees any allocated object inside the variant after the call.

The following example shows a formatted value type.

Public Structure ObjectHolder
   Dim o1 As Object
   <MarshalAs(UnmanagedType.IDispatch)> Public o2 As Object
End Structure
public struct ObjectHolder {
   Object o1;
   [MarshalAs(UnmanagedType.IDispatch)]public Object o2;
}

The following code exports the formatted type to a type library.

struct ObjectHolder {
   VARIANT o1;
   IDispatch *o2;
}
Marshalling Object to Interface

When an object is exposed to COM as an interface, that interface is the class interface for the managed type Object (the _Object interface). This interface is typed as an IDispatch (UnmanagedType) or an IUnknown (UnmanagedType.IUnknown) in the resulting type library. COM clients can dynamically invoke the members of the managed class or any members implemented by its derived classes through the _Object interface. The client can also call QueryInterface to obtain any other interface explicitly implemented by the managed type.

Marshalling Object to Variant

When an object is marshalled to a variant, the internal variant type is determined at run time, based on the following rules:

Marshalling System Types to Variant

The following table shows managed object types and their corresponding COM variant types. These types are converted only when the signature of the method being called is of type System.Object.

Using the MarshalObject interface defined in the previous example, the following code example demonstrates how to pass various types of variants to a COM server.

Dim mo As New MarshalObject()
mo.SetVariant(Nothing)         ' Marshal as variant of type VT_EMPTY.
mo.SetVariant(System.DBNull.Value) ' Marshal as variant of type VT_NULL.
mo.SetVariant(CInt(27))        ' Marshal as variant of type VT_I2.
mo.SetVariant(CLng(27))        ' Marshal as variant of type VT_I4.
mo.SetVariant(CSng(27.0))      ' Marshal as variant of type VT_R4.
mo.SetVariant(CDbl(27.0))      ' Marshal as variant of type VT_R8.
MarshalObject mo = new MarshalObject();
mo.SetVariant(null);            // Marshal as variant of type VT_EMPTY.
mo.SetVariant(System.DBNull.Value); // Marshal as variant of type VT_NULL.
mo.SetVariant((int)27);          // Marshal as variant of type VT_I2.
mo.SetVariant((long)27);          // Marshal as variant of type VT_I4.
mo.SetVariant((single)27.0);   // Marshal as variant of type VT_R4.
mo.SetVariant((double)27.0);   // Marshal as variant of type VT_R8.

COM types that do not have corresponding managed types can be marshalled using wrapper classes such as ErrorWrapper, DispatchWrapper, UnknownWrapper, and CurrencyWrapper. The following code example demonstrates how to use these wrappers to pass various types of variants to a COM server.

Imports System.Runtime.InteropServices
' Pass inew as a variant of type VT_UNKNOWN interface.
mo.SetVariant(New UnknownWrapper(inew))
' Pass inew as a variant of type VT_DISPATCH interface.
mo.SetVariant(New DispatchWrapper(inew))
' Pass a value as a variant of type VT_ERROR interface.
mo.SetVariant(New ErrorWrapper(&H80054002))
' Pass a value as a variant of type VT_CURRENCY interface.
mo.SetVariant(New CurrencyWrapper(New Decimal(5.25)))
using System.Runtime.InteropServices;
// Pass inew as a variant of type VT_UNKNOWN interface.
mo.SetVariant(new UnknownWrapper(inew));
// Pass inew as a variant of type VT_DISPATCH interface.
mo.SetVariant(new DispatchWrapper(inew));
// Pass a value as a variant of type VT_ERROR interface.
mo.SetVariant(new ErrorWrapper(0x80054002));
// Pass a value as a variant of type VT_CURRENCY interface.
mo.SetVariant(new CurrencyWrapper(new Decimal(5.25)));

The wrapper classes are defined in the System.Runtime.InteropServices namespace.

Marshalling the IConvertible Interface to Variant

Types other than those listed in the previous section can control how they are marshalled by implementing the IConvertible interface. If the object implements the IConvertible interface, the COM variant type is determined at run time by the value of the TypeCode enumeration returned from the IConvertible.GetTypeCode method.

The following table shows the possible values for the TypeCode enumeration and the corresponding COM variant type for each value.

TypeCode COM variant type TypeCode.Empty VT_EMPTY TypeCode.Object VT_UNKNOWN TypeCode.DBNull VT_NULL TypeCode.Boolean VT_BOOL TypeCode.Char VT_UI2 TypeCode.Sbyte VT_I1 TypeCode.Byte VT_UI1 TypeCode.Int16 VT_I2 TypeCode.UInt16 VT_UI2 TypeCode.Int32 VT_I4 TypeCode.UInt32 VT_UI4 TypeCode.Int64 VT_I8 TypeCode.UInt64 VT_UI8 TypeCode.Single VT_R4 TypeCode.Double VT_R8 TypeCode.Decimal VT_DECIMAL TypeCode.DateTime VT_DATE TypeCode.String VT_BSTR Not supported. VT_INT Not supported. VT_UINT Not supported. VT_ARRAY Not supported. VT_RECORD Not supported. VT_CY Not supported. VT_VARIANT

The value of the COM variant is determined by calling the IConvertible.To Type interface, where To Type is the conversion routine that corresponds to the type that was returned from IConvertible.GetTypeCode. For example, an object that returns TypeCode.Double from IConvertible.GetTypeCode is marshalled as a COM variant of type VT_R8. You can obtain the value of the variant (stored in the dblVal field of the COM variant) by casting to the IConvertible interface and calling the ToDouble method.

Marshalling Variant to Object

When marshalling a variant to an object, the type, and sometimes the value, of the marshalled variant determines the type of object produced. The following table identifies each variant type and the corresponding object type that the m marshallerreates when a variant is passed from COM to the .NET Framework.

Variant types passed from COM to managed code and then back to COM might not retain the same variant type for the duration of the call. Consider what happens when a variant of type VT_DISPATCH is passed from COM to the .NET Framework. During marshalling, the variant is converted to a System.Object. If the Object is then passed back to COM, it is marshalled back to a variant of type VT_UNKNOWN. There is no guarantee that the variant produced when an object is marshalled from managed code to COM will be the same type as the variant initially used to produce the object.

Marshalling ByRef Variants

Although variants themselves can be passed by value or by reference, the VT_BYREF flag can also be used with any variant type to indicate that the contents of the variant are being passed by reference instead of by value. The difference between marshalling variants by reference and marshalling a variant with the VT_BYREF flag set can be confusing. The following illustration clarifies the differences:

Variants passed by value and by reference

Default behavior for marshalling objects and variants by value

Default behavior for marshalling objects and variants by reference

To propagate changes back to the caller, the parameters must be passed by reference. For example, you can use the ref keyword in C# (or ByRef in Visual Basic managed code) to pass parameters by reference. In COM, reference parameters are passed using a pointer such as a variant *.

Default behavior for marshalling a variant with the VT_BYREF flag set

The following table summarizes the propagation rules for variants and objects.

From To Changes propagated back Variant v Object o Never Object o Variant v Never Variant * pv Ref Object o Always Ref object o Variant * pv Always Variant v (VT_BYREF | VT_*) Object o Never Variant v (VT_BYREF | VT_) Ref Object o Only if the type has not changed. See also

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4