Skip to content

Commit

Permalink
Add dispId to ComProperty and use value to simplify COM calls (skip G…
Browse files Browse the repository at this point in the history
…etIDsOfNames)

dispIDs can be queried via GetIDsOfNames at runtime or retrieved from the
typelibrary when bindings are generated.

Using the dispID eliminates one additional call into native environment.

It was also observed, that runtime reflection sometimes retrieves wrong
values (toString on IHTMLDocument2), so using a previously retrieved value
seems to be saver.
  • Loading branch information
matthiasblaesing committed Mar 11, 2016
1 parent 4e21b32 commit 596022a
Show file tree
Hide file tree
Showing 4 changed files with 292 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@
*/
package com.sun.jna.platform.win32.COM.util;

import com.sun.jna.platform.win32.OaIdl.DISPID;

/**
* Java friendly version of {@link com.sun.jna.platform.win32.COM.IDispatch}.
*
*/
public interface IDispatch extends IUnknown {

<T> void setProperty(String name, T value);
<T> T getProperty(Class<T> returnType, String name, Object... args);
<T> T invokeMethod(Class<T> returnType, String name, Object... args);
<T> void setProperty(DISPID dispid, T value);
<T> T getProperty(Class<T> returnType, DISPID dispid, Object... args);
<T> T invokeMethod(Class<T> returnType, DISPID dispid, Object... args);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;

Expand Down Expand Up @@ -227,21 +226,35 @@ public Object invoke(final Object proxy, final java.lang.reflect.Method method,

ComProperty prop = method.getAnnotation(ComProperty.class);
if (null != prop) {
int dispId = prop.dispId();
if (isVoid) {
String propName = this.getMutatorName(method, prop);
this.setProperty(propName, args[0]);
return null;
if(dispId != -1) {
this.setProperty(new DISPID(dispId), args[0]);
return null;
} else {
String propName = this.getMutatorName(method, prop);
this.setProperty(propName, args[0]);
return null;
}
} else {
String propName = this.getAccessorName(method, prop);
return this.getProperty(returnType, propName, args);
if(dispId != -1) {
return this.getProperty(returnType, new DISPID(dispId), args);
} else {
String propName = this.getAccessorName(method, prop);
return this.getProperty(returnType, propName, args);
}
}
}

ComMethod meth = method.getAnnotation(ComMethod.class);
if (null != meth) {
String methName = this.getMethodName(method, meth);
Object res = this.invokeMethod(returnType, methName, args);
return res;
int dispId = meth.dispId();
if(dispId != -1) {
return this.invokeMethod(returnType, new DISPID(dispId), args);
} else {
String methName = this.getMethodName(method, meth);
return this.invokeMethod(returnType, methName, args);
}
}

return null;
Expand Down Expand Up @@ -328,42 +341,58 @@ public void unadvise(Class<?> comEventCallbackInterface, final IComEventCallback
// --------------------- IDispatch ------------------------------
@Override
public <T> void setProperty(String name, T value) {
DISPID dispID = resolveDispId(this.getRawDispatch(), name);
setProperty(dispID, value);
}

@Override
public <T> void setProperty(DISPID dispId, T value) {
assert COMUtils.comIsInitialized() : "COM not initialized";

VARIANT v = Convert.toVariant(value);
WinNT.HRESULT hr = this.oleMethod(OleAuto.DISPATCH_PROPERTYPUT, null, this.getRawDispatch(), name, v);
WinNT.HRESULT hr = this.oleMethod(OleAuto.DISPATCH_PROPERTYPUT, null, this.getRawDispatch(), dispId, v);
Convert.free(v, value); // Free value allocated by Convert#toVariant
COMUtils.checkRC(hr);
}

@Override
public <T> T getProperty(Class<T> returnType, String name, Object... args) {
assert COMUtils.comIsInitialized() : "COM not initialized";

VARIANT[] vargs;
if (null == args) {
vargs = new VARIANT[0];
} else {
vargs = new VARIANT[args.length];
}
for (int i = 0; i < vargs.length; ++i) {
vargs[i] = Convert.toVariant(args[i]);
}
Variant.VARIANT.ByReference result = new Variant.VARIANT.ByReference();
WinNT.HRESULT hr = this.oleMethod(OleAuto.DISPATCH_PROPERTYGET, result, this.getRawDispatch(), name, vargs);

for (int i = 0; i < vargs.length; i++) {
// Free value allocated by Convert#toVariant
Convert.free(vargs[i], args[i]);
}

COMUtils.checkRC(hr);

return convertAndFreeReturn(result, returnType);
DISPID dispID = resolveDispId(this.getRawDispatch(), name);
return getProperty(returnType, dispID, args);
}

@Override
public <T> T getProperty(Class<T> returnType, DISPID dispID, Object... args) {
VARIANT[] vargs;
if (null == args) {
vargs = new VARIANT[0];
} else {
vargs = new VARIANT[args.length];
}
for (int i = 0; i < vargs.length; ++i) {
vargs[i] = Convert.toVariant(args[i]);
}
Variant.VARIANT.ByReference result = new Variant.VARIANT.ByReference();
WinNT.HRESULT hr = this.oleMethod(OleAuto.DISPATCH_PROPERTYGET, result, this.getRawDispatch(), dispID, vargs);

for (int i = 0; i < vargs.length; i++) {
// Free value allocated by Convert#toVariant
Convert.free(vargs[i], args[i]);
}

COMUtils.checkRC(hr);

return convertAndFreeReturn(result, returnType);
}

@Override
public <T> T invokeMethod(Class<T> returnType, String name, Object... args) {
DISPID dispID = resolveDispId(this.getRawDispatch(), name);
return invokeMethod(returnType, dispID, args);
}

@Override
public <T> T invokeMethod(Class<T> returnType, DISPID dispID, Object... args) {
assert COMUtils.comIsInitialized() : "COM not initialized";

VARIANT[] vargs;
Expand All @@ -376,7 +405,7 @@ public <T> T invokeMethod(Class<T> returnType, String name, Object... args) {
vargs[i] = Convert.toVariant(args[i]);
}
Variant.VARIANT.ByReference result = new Variant.VARIANT.ByReference();
WinNT.HRESULT hr = this.oleMethod(OleAuto.DISPATCH_METHOD, result, this.getRawDispatch(), name, vargs);
WinNT.HRESULT hr = this.oleMethod(OleAuto.DISPATCH_METHOD, result, this.getRawDispatch(), dispID, vargs);

for (int i = 0; i < vargs.length; i++) {
// Free value allocated by Convert#toVariant
Expand Down Expand Up @@ -524,11 +553,9 @@ protected HRESULT oleMethod(int nType, VARIANT.ByReference pvResult, IDispatch p
return this.oleMethod(nType, pvResult, pDisp, dispId, (VARIANT[]) null);
}

/*
* @see com.sun.jna.platform.win32.COM.COMBindingBaseObject#oleMethod
*/
protected HRESULT oleMethod(int nType, VARIANT.ByReference pvResult, final IDispatch pDisp, String name,
VARIANT[] pArgs) throws COMException {
protected DISPID resolveDispId(final IDispatch pDisp, String name) {
assert COMUtils.comIsInitialized() : "COM not initialized";

if (pDisp == null)
throw new COMException("pDisp (IDispatch) parameter is null!");

Expand All @@ -541,8 +568,17 @@ protected HRESULT oleMethod(int nType, VARIANT.ByReference pvResult, final IDisp
pdispID);

COMUtils.checkRC(hr);

return pdispID.getValue();
}

/*
* @see com.sun.jna.platform.win32.COM.COMBindingBaseObject#oleMethod
*/
protected HRESULT oleMethod(int nType, VARIANT.ByReference pvResult, final IDispatch pDisp, String name,
VARIANT[] pArgs) throws COMException {

return this.oleMethod(nType, pvResult, pDisp, pdispID.getValue(), pArgs);
return this.oleMethod(nType, pvResult, pDisp, resolveDispId(pDisp, name), pArgs);
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@
@Inherited
public @interface ComProperty {
String name() default "";
int dispId() default -1; //default to dispid unknown
}
Loading

0 comments on commit 596022a

Please sign in to comment.