tcom -- Access COM objects from Tcl
The tcom package provides commands to access COM objects and invoke methods on them. The package uses the IDispatch interface to discover the interface exposed by the object, and to implement method invocation.
The ::tcom::ref command gets a reference to a COM object through an interface pointer. The command returns a handle representing the interface pointer. The handle can be used as a Tcl command to invoke operations on the object. In practice, you should store this return value in a Tcl variable or pass it as an argument to another command. The createobject subcommand creates an instance of the object. The getobject subcommand gets a reference to an already existing object. The progID parameter is the program ID specifying the object class. Use the -clsid option if you want to specify the class using a class ID instead of a program ID. The hostName parameter specifies the machine where you want to create the object instance.
The ::tcom::release command closes the connection to the object represented by the handle. You cannot use the handle after it has been released.
This command invokes a method on the object represented by the handle. The return value of the method is returned as a Tcl value. A Tcl error will be raised if the method returns a failure HRESULT code. In parameters are passed by value. For out and in/out parameters, pass Tcl variable names as arguments. After the method returns, the variables will contain the result values.
Use the -namedarg option to invoke a method with named arguments. This only works with objects that implement IDispatch. You specify arguments by passing name and value pairs.
This command gets or sets a property of the object represented by the handle. If you supply a value argument, this command sets the named property to the value, otherwise it returns the property value. For indexed properties, you must specify one or more index values. The command raises a Tcl error if you specify an invalid property name or if you try to set a value that cannot be converted to the property's type.
If the object's interface defines a method with the same name as a property, you must use the -property option.
This command specifies a Tcl command to execute in order to process events generated by an object. The command will be called with additional arguments: the event name and the event arguments. By default, the event interface is the default event source interface of the object's class. Use the sourceIID parameter to specify the IID of another event interface.
Objects that implement the IDispatch interface allow some method parameters to be optional. This command returns a token representing a missing optional argument. In practice, you would pass this token as a method argument in place of a missing optional argument.
This command returns a handle representing a description of the interface exposed by the object. You should release this handle using the ::tcom::release command. This interface handle supports the following commands.
This command returns an interface identifier code.
This command returns a list of method descriptions for methods defined in the interface. Each method description is a list. The first element is the member ID. The second element is the return type. The third element is the method name. The fourth element is a list of parameter descriptions.
This command returns the interface's name.
This command returns a list of property descriptions for properties defined in the interface. Each property description is a list. The first element is the member ID. The second element is the property read/write mode. The third element is the property data type. The fourth element is the property name. If the property is an indexed property, there is a fifth element which is a list of parameter descriptions.
This command sets and retrieves options for the package. If name is supplied but no value then the command returns the current value of the given option. If one or more pairs of name and value are supplied, the command sets each of the named options to the corresponding value; in this case the return value is an empty string.
This option sets the concurrency model, which can be apartmentthreaded or multithreaded. The default is apartmentthreaded. You must configure this option before performing any COM operations such as getting a reference to an object. After a COM operation has been done, changing this option has no effect.
Use the ::tcom::import command to convert type information from a type library into Tcl commands to access COM classes and interfaces. The typeLibrary argument specifies a type library file. By default, the commands are defined in a namespace named after the type library, but you may specify another namespace by supplying a namespace argument. This command returns the library name stored in the type library file.
For each class in the type library, ::tcom::import defines a Tcl command with the same name as the class. The class command creates an object of the class and returns a handle representing the object. The command accepts an optional hostName argument to specify the machine where you want to create the object. You can use the returned handle to invoke methods and access properties of the object. In practice, you should store this handle in a Tcl variable or pass it as an argument to a Tcl command.
When you are done with the object reference, you should release the handle by calling the ::tcom::release command.
For each interface in the type library, ::tcom::import defines a Tcl command with the same name as the interface. The interface command takes an existing object reference and creates a new reference that implements the interface. The commands returns a handle representing the new object reference. You can use the returned handle to invoke methods and access properties of the object. In practice, you should store this handle in a Tcl variable or pass it as an argument to a Tcl command.
When you are done with the object reference, you should release the handle by calling the ::tcom::release command.
The ::tcom::import generates a Tcl array for each enumeration defined in the type library. The array name is the enumeration name. To get an enumerator value, use an enumerator name as an index into the array.
Values in Tcl are dual-ported objects. Tcl objects have a string representation but also hold an internal representation that can be manipulated more efficiently. For example, a Tcl list is represented as an object that holds the list's string representation as well as an array of pointers to the objects for each list element. The two representations are a cache of each other and are computed lazily. That is, each representation is only computed when necessary, is computed from the other representation, and, once computed, is saved. In addition, a change in one representation invalidates the other one. As an example, a Tcl program doing integer calculations can operate directly on a variable's internal machine integer representation without having to constantly convert between integers and strings. Only when it needs a string representing the variable's value, say to print it, will the program regenerate the string representation from the integer. The internal representations built into Tcl include boolean, integer and floating point types.
When calling COM object methods, tcom tries to convert each Tcl argument to the parameter type specified by the method interface. For example, if a method accepts an int parameter, tcom tries to convert the argument to that type. If the parameter type is a VARIANT, the conversion has an extra complication because a VARIANT is designed to hold many different data types. One approach might be to simply copy the Tcl object's string representation to a string in the VARIANT, and hope the implementation can correctly interpret the string, but this doesn't work in general because some implementations expect certain VARIANT types.
Tcom uses the Tcl object's internal representation type as a hint to choose the resulting VARIANT type.
Tcl object to VARIANT mapping
Tcl internal representation VARIANT type boolean VT_BOOL int VT_I4 double VT_R8 list one-dimensional array of VT_VARIANT bytearray one-dimensional array of VT_UI1 other VT_BSTR
The standard interface for COM collections defines the Item method for getting an element by specifying an index. Many implementations of the method allow the index to be an integer value (usually based from 1) or a string key. The index parameter is a VARIANT, so you must account for the internal representation type of the Tcl argument passed to that parameter.
# Assume $collection is a reference to a collection. set element [$collection Item 1] |
This command passes the string consisting of the single character "1" to the Item method. The method may return an error because it can't find an element with that string key.
set numElements [$collection Count] for {set i 1} {$i <= $numElements} {incr i} { ;# 1 set element [$collection Item $i] ;# 2 } |
In line 1, the for command sets the internal representation of $i to an int type as a side effect of evaluating the condition expression {$i <= $numElements}. The command in line 2 passes the integer value in $i to the Item method, which should succeed if the method can handle integer index values.