210 likes | 494 Views
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
E N D
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 ErlComDrv.dll erl_com thread IWhatever
Comet as a Port Program • An application calling a COM Object • Comet as a port program Erlang process some_application ErlComDrv.exe erl_com 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 • 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()}]) 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 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 ... [Outstr]= erl_com:com_call(I_, 36, [{vt_str, InStr}, {vt_str, out}]), ...
{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 2 3 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”
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)