Directory UMM :Networking Manual:computer_network_books:
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
OTP release 7B
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
Support for distribution, DCOM and COM+
COM Model
Classes presents interfaces
Interfaces are a bunch of related functions or methods
No data are exposed, only interfaces
Properties of objects accessible through access-functions
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
Comet can use both (although dispatch is safer)
COM Memory Handling
Reference-counting
Language support in Visual Basic, “Java” (and C#)
Erlang programs must (currently) explicitly free interfaces
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
The Comet port driver and program are multithreaded
Comet as a Port Driver
An application calling a COM Object
– Comet as a driver
Erlang process
some_application
erl_com
ErlComDrv.dll
thread
IWhatever
Comet as a Port Program
An application calling a COM Object
– Comet as a port program
Erlang process
some_application
erl_com
ErlComDrv.exe
thread
IWhatever
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
asynchronously
A Simple Example
An interface that implements some utilities
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);
...
};
Calling it from Erlang
...
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()}])
erl_com:release(I),
...
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
Complex types as structures, are currently not supported
Invoke (dispatch interface)
The invoke method in the dispatch interface is used to latebind to interfaces
Comet provides the methods invoke, property_put and
property_get
...
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”),
...
Errors returned as {com_error, Code}
Can have named parameters (not support in Comet yet)
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
...
[Outstr]= erl_com:com_call(I_, 36, [{vt_str, InStr}, {vt_str, out}]),
...
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(),
1
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"]),
3
erl_com:property_put(Obj, "Visible", true),
Obj.
2
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"),
C= erl_com:package_interface(E, erl_com:property_get(E, "ActiveChart")),
erl_com:property_put(C, "ChartType", ?XlPieExploded),
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
header-file with macros
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),
chart:location(ActiveChart, ?xlLocationAsObject, "Sheet1"),
Problems
Combining an object-oriented approach with Erlang’s
semi-functional
Handling state
Memory management
Type conversions between Erlang and other system
Asynchronous operations
Performance considerations
Robustness
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
– Combining COM’s ref-counting with Erlang’s GC
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
Wesley)
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
OTP release 7B
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
Support for distribution, DCOM and COM+
COM Model
Classes presents interfaces
Interfaces are a bunch of related functions or methods
No data are exposed, only interfaces
Properties of objects accessible through access-functions
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
Comet can use both (although dispatch is safer)
COM Memory Handling
Reference-counting
Language support in Visual Basic, “Java” (and C#)
Erlang programs must (currently) explicitly free interfaces
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
The Comet port driver and program are multithreaded
Comet as a Port Driver
An application calling a COM Object
– Comet as a driver
Erlang process
some_application
erl_com
ErlComDrv.dll
thread
IWhatever
Comet as a Port Program
An application calling a COM Object
– Comet as a port program
Erlang process
some_application
erl_com
ErlComDrv.exe
thread
IWhatever
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
asynchronously
A Simple Example
An interface that implements some utilities
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);
...
};
Calling it from Erlang
...
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()}])
erl_com:release(I),
...
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
Complex types as structures, are currently not supported
Invoke (dispatch interface)
The invoke method in the dispatch interface is used to latebind to interfaces
Comet provides the methods invoke, property_put and
property_get
...
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”),
...
Errors returned as {com_error, Code}
Can have named parameters (not support in Comet yet)
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
...
[Outstr]= erl_com:com_call(I_, 36, [{vt_str, InStr}, {vt_str, out}]),
...
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(),
1
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"]),
3
erl_com:property_put(Obj, "Visible", true),
Obj.
2
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"),
C= erl_com:package_interface(E, erl_com:property_get(E, "ActiveChart")),
erl_com:property_put(C, "ChartType", ?XlPieExploded),
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
header-file with macros
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),
chart:location(ActiveChart, ?xlLocationAsObject, "Sheet1"),
Problems
Combining an object-oriented approach with Erlang’s
semi-functional
Handling state
Memory management
Type conversions between Erlang and other system
Asynchronous operations
Performance considerations
Robustness
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
– Combining COM’s ref-counting with Erlang’s GC
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
Wesley)