COM in 3 minutes

Microsoft COM (= Component Object Model) is object-based interoperability infrastructure. In other words, COM provides object-based shared library and inter process communication. OLE is upper layer of COM.

Compared to shared library, COM is characterized as follows.

Shared library

  • Library name is a path in a file system.
  • Library exports functions.

COM

Component name is UUID.

A component is identified by UUID, which is 128bit almost global unique ID. For example, Microsoft Internet Explorer has its UUID:

{0002DF01-0000-0000-C000-000000000046}

COM infrastructure manages mapping between UUID and the location of implementation code of the service identified by the UUID. In Windows, static information about this mapping is stored in registry. For the above UUID, the registry has an entry at

HKEY_CLASSES_ROOT\CLSID\{0002DF01-0000-0000-C000-000000000046}

By using C:/WINDOWS/regedit.exe, you can see there that the UUID is mapped to an executable file:

"C:\Program Files\Internet Explorer\iexplore.exe"

Component exports object.

From client, COM object is seen as a pair of instance data and an array of function pointers. Its layout resembles those of object which Microsoft C++ compiler generates. So, a COM object is seen as an usual object in C++ program if you use MS compiler.

The following is an approximate code in pseudo C to access Internet Explorer.

typedef struct tagIInternetExplorerVtbl
{
  void (*setVisible)(IInternetExplorer* this, bool visible);
  bool (*getVisible)(IInternetExplorer* this);
  void (*navigate)(IInternetExplorer* this, string url);
  void (*quit)(IInternetExplorer* this);
} IInternetExplorerVtbl;

typedef struct tagIInternetExplorer
{
  IInternetExplorerVtbl* vtbl;
} IInternetExplorer;

UUID IEUUID = {0002DF01-0000-0000-C000-000000000046};

IInternetExplorer* ie = (IInternetExplorer*)CoCreateInstance(IEUUID);

ie->vtbl->setVisible(ie, true);
ie->vtbl->navigate(ie, "http://www.pllab.riec.tohoku.ac.jp/smlsharp/");
ie->vtbl->quit(ie);

Topics in OLE/SML#.

OLE/SML# is a support tool to enable SML code to access Microsoft COM/OLE objects.

OLE/SML# depends on SML# features including FFI, LMLML, Finalizer and FLOB.

Components.

OLE2SML.exe
Given a type library, this command generates SML# source code to access COM objects which are described in the type library.
OLE.sml
Base library to access Microsoft COM infrastructure.

Usage.

OLE2SML.exe generates SML code from user specified type library.

$ OLE.exe [options] TYPELIB_FILENAME
$ OLE.exe [options] ProgID

Type library can be specified by

  • file path of the type library, or
  • ProgID of a Coclass of which type information is described in the type library.

Options:

-c CLASSNAME
generates wrapper codes for specified coclasses or dispatch interfaces only. You can use this option more than once. If no -c option is specified, wrappers for all coclasses and dispatch interfaces are generated.
-o FILENAME
writes wrapper code into the specified file name. If no -o option is specified, file name is TYPELIBNAME.sml .
-h
shows usage.

Example.

For example, let's write a SML# code to operate Internet Explorer (=IE).

First, use OLE2SML.exe to generate a wrapper code for IE.

OLE2SML takes a ProgID as its command line parameter. ProgID of IE is "InternetExplorer.Application".

$ OLE2SML.exe InternetExplorer.Application

Instead of ProgID, you can specify the file path of the type library.

$ OLE2SML.exe "C:\\WINDOWS\\System32\\shdocvw.dll"

The type library C:\WINDOWS\System32\shdocvw.dll defines COM objects implemented in Internet Explorer.

By default, OLE2SML.exe generates code for every coclass and interfaces described in the specified type library. If you use only some of them, you can specify them with -c option to reduce the size of generated code.

$ OLE2SML.exe -c InternetExplorer InternetExplorer.Application
$ OLE2SML.exe -c InternetExplorer "C:\\WINDOWS\\System32\\shdocvw.dll"

The generated code contains code for InternetExplorer coclass only.

The following session creates an IE instance, navigates to Home page.

# use "OLE.sml";
    :
# OLE.initialize [OLE.COINIT_MULTITHREADED];
val it = () : unit

Loads and initializes the OLE library.

# use "./SHDocVw.sml";
signature SHDocVw =
    :
end
structure SHDocVw : SHDocVw

Loads the generated wrapper code for IE. The wrapper code defines a structure with the name of the type library.

# val IE = SHDocVw.newInternetExplorer ();
val IE =
   {
     :
   }
   : SHDocVw.InternetExplorer

Creates an instance of IE. newcoclass is the constructor function of coclass.

# #getVisible IE ();
val it = false : bool
# #setVisible IE true;
val it = () : unit

Accesses the visible property of IE.

# #GoHome IE ();
val it = () : unit

Invokes the GoHome method of IE.

# #release IE ();
val it = 0wx0 : Word32.word

COM manages the life cycle of objects by reference count. OLE/SML# manages reference count of each COM object internally, depending on GC of SML#, so you does not have to call addRef and release explicitly. In this example, however, the reference to an IE object is bound at global. Because a global binding will not become garbage in GC of SML#, you have to call release after use, so that global binding is released.

# OLE.uninitialize ();
val it = () : unit

Clean-up OLE library.

Other examples.

Last modified:2010/06/11 15:07:35
Keyword(s):
References:[OLE/SML#] [implementation overview of OLE/SML#] [mapping COM and SML#] [COM in 3 minutes] [Oveview of OLE/SML#]