mapping COM and SML#
IDispatch and Variant.
OLE/SML# interoperates with COM objects through IDispatch interface.
Methods exposed by COM objects are accessed via IDispatch::Invoke.
IDispatch::Invoke takes and returns OLE Variant. Variant is a tagged union of various data types.
data type mapping.
Data types which can be stored in Variant are enumerated in VARENUM. Data types indicated by VARENUM are mapped to SML# datatype as follows.
| VARENUM | SML# data type |
|---|---|
| VT_EMPTY | unsupported |
| VT_NULL | unsupported |
| VT_I2 | Int32.int |
| VT_I4 | Int32.int |
| VT_R4 | Real32.real |
| VT_R8 | Real64.real |
| VT_CY | unsupported |
| VT_DATE | unsupported |
| VT_BSTR | OLE.string |
| VT_DISPATCH | OLE.Dispatch |
| VT_ERROR | unsupported |
| VT_BOOL | bool |
| VT_VARIANT | OLE.variant |
| VT_UNKNOWN | OLE.Unknown |
| VT_DECIMAL | OLE.decimal |
| VT_I1 | Int32.int |
| VT_UI1 | Word8.word |
| VT_UI2 | Word32.word |
| VT_UI4 | Word32.word |
| VT_I8 | IntInf.int |
| VT_UI8 | IntInf.int |
| VT_INT | Int32.int |
| VT_UINT | Word32.word |
| VT_VOID | unit |
| VT_HRESULT | unsupported |
| VT_PTR(vt) | OLE.variant |
| VT_SAFEARRAY(vt) | [SML# type of vt] OLE.safearray |
| VT_CARRAY | unsupported |
| VT_USERDEFINED(TKIND_DISPATCH) | OLE.Dispatch |
| VT_USERDEFINED(TKIND_COCLASS) | OLE.Dispatch |
| VT_USERDEFINED(TKIND_ENUM) | Int32.int |
| VT_USERDEFINED(other type) | unsupported |
| VT_LPSTR | unsupported |
| VT_LPWSTR | unsupported |
| VT_RECORD | unsupported |
| VT_INT_PTR | unsupported |
| VT_UINT_PTR | unsupported |
| VT_FILETIME | unsupported |
| VT_BLOB | unsupported |
| VT_STREAM | unsupported |
| VT_STORAGE | unsupported |
| VT_STREAMED_OBJECT | unsupported |
| VT_STORED_OBJECT | unsupported |
| VT_BLOB_OBJECT | unsupported |
| VT_CF | unsupported |
| VT_CLSID | unsupported |
| VT_BSTR_BLOB | unsupported |
| VT_VECTOR | unsupported |
| VT_ARRAY | unsupported |
| VT_BYREF(vt) | OLE.variant |
SAFEARRAY mapping.
COM SAFEARRAY can describe multi-dimension arrays. OLE/SML# maps a SAFEARRAY to OLE.safearray. For example, a three-dimensional SAFEARRAY
VT_INT a[10][20][30]
is mapped to Int32.int OLE.safearray.
a : Int32.int OLE.safearray
An element of a SAFEARRAY
a[1][2][3]
is accessed as
OLE.SafeArray.sub (a, [1, 2, 3])
In addition to using OLE.SafeArray, you can access an safearray directly. Int32.int OLE.safearray is a pair of an array of Int32.int and a list of int.
(array, [10, 20, 30]) : Int32.int array * int list
The elements of an array are stored in column major order. The first dimension changes first, and the last dimension changes last.
For example, an element of the above SAFEARRAY a
a[1][2][3]
is stored at the index of 3 * (10 * 20) + 2 * 10 + 1 = 621. It can be accessed from SML# as
Array.sub(array, 621)
method mapping.
A COM method which takes n arguments is mapped to a SML# function which takes a tuple of n elements.
If a method is a void function returning nothing, it is mapped to a SML# fuction which returns a unit.
| COM method | SML# function |
|---|---|
| t0 method() | method : unit -> [t0] |
| t0 method(t1) | method : [t1] -> [t0] |
| t0 method(t1, ..., tn) | method : [t1] * ... * [tn] -> [t0] |
In this table,
[t]
indicates the SML# datatype mapped from Variant type t.
parameter mapping.
optional parameter.
An optional parameter of type t is mapped to
[t] option
[out] attribute.
If a parameter is annotated with [out] attribute, the type of the parameter is mapped to OLE.variant ref.
null reference parameter.
Use OLE.NullUnknown and OLE.NullDispatch to pass a null reference in VT_UNKNOWN and VT_DISPATCH parameter.
Use EMPTY to pass a null pointer to other types in VT_VARIANT parameter.
property accessor
In addition to usual methods, COM objects expose three types of methods. These are accessor methods for properties of COM objects.
The getter of a property p of type t is mapped to a SML# function
getp : unit -> [t]
The setter of a property p of type t is mapped to a SML# function
setp : [t] -> unit
The reference setter of a property p of type t is mapped to a SML# function
setRefp : [t] -> unit
Restriction.
OLE structure and OLE2SML ignore methods which satisfy any of following.
- any of its parameters has [ret] attribute.
- any of its parameters is variant type which is not included in OLE.variant.
exception mapping.
If a COM object throws an exception in an invocation of its method from OLE/SML#, an SML# exception
OLE.OLEError(OLE.ComApplicationError detail)
is raised to the caller in SML#.
If COM framework API function returns an error, an SML# exception
OLE.OLEError(ComSystemError message)
is raised to SML# world.
Keyword(s):
References:[mapping .NET/SML#] [mapping COM and SML#] [Oveview of OLE/SML#] [COM in 3 minutes] [OLE/SML#] [implementation overview of OLE/SML#]