Comet - an Erlang-to-COM Port
Comet is a port and a gen_server module that enables
Erlang programs to deploy COM components
Comet is under development, an early version is part of
COM
Common Object Model
A standard for component development from Microsoft Windows-only (although a third-party version exist on
Solaris)
Rival to CORBA on the Windows platform All Microsoft programs use COM
COM Model
Classes presents interfaces
Interfaces are a bunch of related functions or methods No data are exposed, only interfaces
COM Model continued
IDL describes classes and interfaces
IDL compiles into a type-library that can be browsed with
a tool
Two ways to use a class
– Dispatch - a special interface for interpreted languages – Virtual Interface - faster, for compiled languages
COM Memory Handling
Reference-counting
Language support in Visual Basic, “Java” (and C#)
Erlang Ports
A way to call external code from Erlang
Implemented as a linked in driver (DLL) or a port program Comet offers both
– port driver is considerably faster
– port program is safer, if the COM server crashes, it
won’t bring the emulator down
A gen_server module interfaces to the port program or
driver
Comet as a Port Driver
An application calling a COM Object
– Comet as a driver
Erlang process
erl_com
ErlComDrv.dll
IWhatever some_application
Comet as a Port Program
An application calling a COM Object
– Comet as a port program
Erlang process
erl_com
ErlComDrv.exe
IWhatever some_application
Calling COM from Erlang
All calls through the gen_server module “erl_com” erl_com provides methods for calling
erl_com has functions for:
– creating objects – fetching interfaces
– releasing interfaces and objects
– retrieving type information of objects and types – creating threads for calling COM objects
A Simple Example
An interface that implements some utilities
Calling it from Erlang
interface ISomeUtilities : IDispatch {
[id(1)]
HRESULT DaysBetween([in] DATE date1, [in] DATE date2, [out, retval] double* daysBetween); [id(2)]
HRESULT ReplaceAll([in] BSTR inStr, [in] BSTR keyStr, [in] BSTR newStr, [out, retval] BSTR* outStr);
... };
...
S= “It was a dark and stormy night...”,
I= erl_com:create_dispatch(T, “{class id for SomeUtilities}”), S2= erl_com:invoke(I, “ReplaceAll”, [S, “stormy”, “still”]),
D= erl_com:invoke(I, “DaysBetween”, [{vt_date, {{2000, 1, 1}, {0, 0, 0}}}, {vt_date, erlang:now()}])
Mapping COM Types to Erlang
COM uses a small set of types
Comet mapps Erlang types to COM types through the use
of tuples
– Basic types are converted properly: integers, floats,
strings and booleans
– Other types are prefixed in a tuple, e.g. {vt_date {1999, 12, 12}, {}}
Constants in COM are enumerations Strings currently 8-bits in Comet
Invoke (dispatch interface)
The invoke method in the dispatch interface is used to
late-bind to interfaces
Comet provides the methods invoke, property_put and
property_get
Errors returned as {com_error, Code}
Can have named parameters (not support in Comet yet)
...
Obj= erl_com:create_object(T, “{class id}”),
I= erl_com:query_interface(Obj, “{a dispatch interface id}”), Value= erl_com:invoke(I, “Method”, [parameters]),
erl_com:property_put(I, “Property”, [parameters], Value2), Value3= erl_com:property_get(I, “AnotherProperty”),
Calling a Virtual Interface
A virtual interface is an array of function pointers
– Virtual Method Table used for C++ objects
Called in Comet using assembler glue
– Every parameter, including return value, must be
explicitly typed
– Address of virtual function must be specified – Only practical when code is generated
Wrong parameters cause Comet to crash
...
Browser Example
The Internet Explorer browser presents COM interfaces
Example: creating an Internet Explorer and navigating to a
URL
1 opens a Comet process and a thread in it
2 creates an object, retrieves its default interface 3 invokes the methods “navigate” and the “visible”
{ok, Pid}= erl_com:start_process(), T= erl_com:new_thread(Pid),
Obj= erl_com:create_dispatch(T, "InternetExplorer.Application", ? CLSCTX_LOCAL_SERVER),
erl_com:invoke(Obj, "Navigate", ["www.erlang.org"]), erl_com:property_put(Obj, "Visible", true),
Obj.
1
Excel Example
Excel is also accessible through COM
Easiest way is to start with a Visual Basic-program
– The Excel macro recorder can generate these
Example: adding a graph
Visual Basic:
Charts.Add
ActiveChart.ChartType = xlPieExploded
Erlang:
Charts = erl_com:package_interface(E, erl_com:property_get(E, "Charts")), erl_com:invoke(Charts, "Add"),
Generating Glue Code
Can be used for both virtual- and dispatch-interfaces
Type libraries, compiled from COM IDL, describes COM
classes and interfaces
Comet reads information from Type Libraries Erlang modules are generated with glue code Each interface generates a module
Each enum (set of constants) generates a module and a
Excel Example with Generated Code
– (Code is generated from the Excel type-library)
Visual Basic:
Charts.Add
ActiveChart.ChartType = xlPieExploded ActiveChart.SetSourceData _
Source:=Sheets("Sheet1").Range("B2:C4"), _ PlotBy:=xlColumns
ActiveChart.Location Where:=xlLocationAsObject, Name:="Sheet1"
Erlang:
charts:add(xc_Application:charts(E)),
ActiveChart= xc_Application:activeChart(E), chart:chartType(ActiveChart, ?XlPieExploded),
R= sheets:range(xc_Application.sheets(E, “Sheet1”), “B2:C4”), chart:setSourceData(ActiveChart, R, ?xlColumns),
Problems
Combining an object-oriented approach with Erlang’s
semi-functional
Handling state
Memory management
Type conversions between Erlang and other system Asynchronous operations
Future Improvements
Feedback needed
Improvements considered
– Full Unicode support
– Calling Erlang from COM – Event Sinks
– Erlang COM Servers – COM+ Distribution
– Complex types
– Other API’s on other platforms
References
Comet documentation from OTP
Don Box: Essential COM (Addison Wesley)
Box, Brown, Ewald and Sells: Effective COM (Addison
Wesley)
Oberg: Understanding & Programming COM+ (Prentice
Hall)
Jason Pritchard: COM and Corba Side by Side (Addison