This part of the userguide, covers how to use Jawin when calling
scriptable COM interfaces, ie. COM interfaces implementing the
IDispatch interface. The information herein covers the
"low-level" code, close to Jawin. This is the form of code the
Jawin Type Browser
generates - this generated code should be used instead of manually
writing this "low-level" code. If the Jawin Type Browser is not able
to generate complete stub-code for a COM interface, the guidelines in this
document should be followed for manually writing the stub-code.
The COM dictionary is full of cryptic terms and abbrevations that one must know a minimum of to use Jawin succesfully. If terms such as GUID, CLSID, IID or ProgID are only vague known to you, please take the time to read the quick overview of these terms in section 1 in the Userguide - Calling a VTable Based COM Interface document.
As shown in the PowerPoint demo from the
introduction to Jawin,
IDispatch interface on any scriptable
COM object is relatively straightforward:
DispatchPtrobject, using either the
CLSIDfor the relevant COM object.
The following subsections are dedicated to how to use each of these
three groups of methods on the
Note that COM requires that all threads calling a COM object must initialize the COM library. This is done by calling:
After a thread is finished with all COM calls, it should call:
Microsoft MSDN documents the details of these two methods; CoInitializeEx and CoUninitialize.
It should be noted that COM has a special thread model. So if using COM objects in multithreaded applications, you unfortunately have to know at least the basic of this. So please see the section on Threading Issues if using COM objects from several threads.
When finished with the dispatch interface object, the
method must be called to let COM decrease the reference count for
the COM-object, and ultimately destroy the object. This call must happen
on the same thread that created the interface object. And even though
DispatchPtr contains a
tries to release the resources if
close() was not
explicitely called, this can not be relied on, since Java neither
finalize() will ever be called, nor is
it guarenteed from which thread it will be called.
The getters are straightforward, as the caller only needs to
specify the property to retrieve (and additional index(es) for
identifying the exact property value).
offers three methods for this (please refer to the javadoc
for additional information about the specific parameters).
public Object get(String prop) throws COMException;
public Object get(String prop, Object index) throws COMException;
public Object getN(String prop, Object indexes) throws COMException;
After invoking one of these methods the caller only needs to cast the
result to the correct type (and retrieve the simple type if suitable).
The javadoc for
Variant.ReadObject() specifies how
native Variant types are converted into Java types - for most
developers there should be no surprises in conversion (ie. native
int is converted to
To set a property value should be just as straightforward as getting a property value. Again there are three groups of setter-methods, for setting properties taking different numbers of indexes for identifying the property.
public void put(String prop, Object val) throws COMException;
public void put(String prop, Object index, Object val) throws COMException;
public void putN(String prop, Object indexes, Object val) throws COMException;
Because of Java's support for overloaded methods a number of shortcut methods also exists for setting properties of simple types, eg. the following method for setting a 4-byte signed integer (a socalled VT_I4):
public void put(String prop, int val) throws COMException;
If you need detailed control of how Jawin converts Java types into native
Variants the javadoc for
Variant.WriteObject() must be
consulted. But please notice that the
mechanism handles scenarios where the VT_TYPE of a parameter is a
not a 100% fit to a method signature or property. Therefore there
should not be any problems by setting eg. a property requering
unsigned int's with either a long or an int.
If you got this far, you can probably guess that invoking methods on the dispatch interface is mostly just a combination of getting and setting properties, that is passing some values to a method as java Objects, and using any return value as another java Object.
Again the javadoc for respectively
Variant.ReadObject() should be consulted for details
about marshalling and unmarshalling of parameters and return values.
There is one special case that needs a few additional words, the
handling of socalled
parameters are usually used when a method returns several values
(ie. the return value is "not enough"). An example of such a method
int doSomething([in] int inValue, [out] int outValue);
This method "returns" two values: both the usual return value and
the value in the
To use such a method from Jawin, one have to use the
org.jawin.Variant.ByrefHolder class (the name originates
from the term passing by reference instead of the usual by
value). The example below shows the usage of a
ByrefHolder wrapping object. To call the above defined
doSomething method, the Java code should be like:
// the usual in value
Integer inValue = new Integer(42);
// wrap the out value in a ByrefHolder
Variant.ByrefHolder outValueRef = new Variant.ByrefHolder(new Integer(0));
// call the method
Integer result = (Integer)dispatchPtr.invoke("doSomething", inValue, outValueRef);
// unwrap the outValue
Integer outValue = (Integer)outValueRef.getRef();
It should be noted in the above code, that one has to pass an "empty"
object of the correct type to the
This is necessary to get the byref value marshalled into the correct
VT_TYPE (in the example above our "empty" value, is the
When working with arrays in a dispatch interface, one has to know in
some detail how the different java-arrays get marshalled to native
Variants. Especially it is important to understand the difference
between arrays of simple types (like
int) and arrays
of objects (like
Integer). The rules are as follows:
|Java Array||Variant Type||Comments|
||Special case of the below array of Java objects.|
||Each of the individual objects are then marshalled as an ordinary
Variant, eg. a Java array of
|simple type array (eg. ||Examples:
||Another special case of array of Java objects.|
||Another special case of array of Java objects.|
The COM error model uses socalled HRESULT's as return values
to indicate failure of a call. Jawin maps this into the Java
Exception hierarchy by throwing a
org.jawin.COMException on failure. This means that
the user can program in standard Java-style, ie. catching exceptions
and not having to worry about checking return HRESULT's.
Section 5 in the Jawin Architecture document contains
some additional information about the conversion of HRESULT's into
If using COM references in multithreaded applications, you must make yourself comportable with how Jawin handles the threading issues that are present in COM. This is presented in section 6 in the Jawin Architecture document.
Additional resources when working with scriptable COM objects from Jawin
|Copyright (c) 2000-2005, The Jawin Project - LICENSE|
|This documentation was written for version: 2.0, alpha 1 of Jawin.|
|$Id: jawinuserguide_dispatch.html,v 1.6 2004/08/01 21:34:26 arosii_moa Exp $|