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,
using the IDispatch
interface on any scriptable
COM object is relatively straightforward:
DispatchPtr
object, using either the
ProgId
or the CLSID
for the relevant COM
object.get()
and getN()
methods in
DispatchPtr
.put()
and putN()
methods in
DispatchPtr
.invoke()
and invokeN()
methods in DispatchPtr
.
The following subsections are dedicated to how to use each of these
three groups of methods on the DispathPtr
-class.
Note that COM requires that all threads calling a COM object must initialize the COM library. This is done by calling:
Ole32.CoInitialize();
After a thread is finished with all COM calls, it should call:
Ole32.CoUninitialize();
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 close()
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
the DispatchPtr
contains a finalize
-method that
tries to release the resources if close()
was not
explicitely called, this can not be relied on, since Java neither
guarentees that 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). DispatchPtr
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 java.lang.Integer
, etc.).
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 IDispatch
coercion
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.WriteObject()
and 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 [out]
parameters. [out]
parameters are usually used when a method returns several values
(ie. the return value is "not enough"). An example of such a method
could be:
int doSomething([in] int inValue, [out] int outValue);
This method "returns" two values: both the usual return value and
the value in the outValue
parameter.
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 ByrefHolder
constructor.
This is necessary to get the byref value marshalled into the correct
VT_TYPE (in the example above our "empty" value, is the
new Integer(0)
).
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 |
---|---|---|
String[] |
VT_ARRAY | VT_BSTR |
Special case of the below array of Java objects. |
Object[] |
VT_ARRAY | VT_VARIANT |
Each of the individual objects are then marshalled as an ordinary
Variant, eg. a Java array of Integer -objects are
marshalled as VT_ARRAY | VT_VARIANT (VT_UI4) . One
can pass arrays of different Variant types, eg. the following is
possiblenew Object[]{ "some string" , new Integer(42) ,
Boolean.TRUE } |
simple type array (eg. int[] ) | VT_ARRAY |
VT for simple type | Examples:int[] -> VT_ARRAY | VT_UI4 double[] -> VT_ARRAY | VT_R8 |
DispatchPtr[] (or subclass) |
VT_ARRAY | VT_DISPATCH |
Another special case of array of Java objects. |
UnknownPtr[] (or subclass) |
VT_ARRAY | VT_UNKNOWN |
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
COMException
s.
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 $ |