Skip to content

Commit 4b7421c

Browse files
committed
Merge pull request #642 from SevenOf9Sleeper/com_proxy_allows_ellipsis
feature #630: use of ellipsis/varargs in COM methods
2 parents 4ba3c1d + a7fb1e5 commit 4b7421c

File tree

3 files changed

+91
-4
lines changed

3 files changed

+91
-4
lines changed

CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ Features
4848
* [#621](https://github.com/java-native-access/jna/pull/621): Added TYPEFLAGS-constants for `wTypeFlags` in `com.sun.jna.platform.win32.OaIdl.TYPEATTR` - [@SevenOf9Sleeper](https://github.com/SevenOf9Sleeper).
4949
* [#625](https://github.com/java-native-access/jna/pull/625): Make conversion to/from java to/from VARIANT in `com.sun.jna.platform.win32.COM.util.Convert` more flexible and dependable - [@matthiasblaesing](https://github.com/matthiasblaesing).
5050
* [#639](https://github.com/java-native-access/jna/pull/639): Add getloadavg() to OS X and Unix - [@dbwiddis](https://github.com/dbwiddis).
51+
* [#642](https://github.com/java-native-access/jna/pull/642): COM calls with variable number of arguments (varargs) are now supported - [@SevenOf9Sleeper](https://github.com/SevenOf9Sleeper).
5152

5253
Bug Fixes
5354
---------

contrib/platform/src/com/sun/jna/platform/win32/COM/util/ProxyObject.java

+19-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
package com.sun.jna.platform.win32.COM.util;
1414

1515
import java.lang.reflect.InvocationHandler;
16+
import java.lang.reflect.InvocationTargetException;
1617
import java.lang.reflect.Proxy;
1718
import java.util.concurrent.ExecutionException;
1819
import java.util.concurrent.TimeoutException;
@@ -51,7 +52,6 @@
5152
import com.sun.jna.platform.win32.COM.util.annotation.ComProperty;
5253
import com.sun.jna.ptr.IntByReference;
5354
import com.sun.jna.ptr.PointerByReference;
54-
import java.lang.reflect.InvocationTargetException;
5555

5656
/**
5757
* This object acts as the invocation handler for interfaces annotated with
@@ -232,12 +232,13 @@ public Object invoke(final Object proxy, final java.lang.reflect.Method method,
232232

233233
ComMethod meth = method.getAnnotation(ComMethod.class);
234234
if (null != meth) {
235+
Object[] fullLengthArgs = unfoldWhenVarargs(method, args);
235236
int dispId = meth.dispId();
236237
if(dispId != -1) {
237-
return this.invokeMethod(returnType, new DISPID(dispId), args);
238+
return this.invokeMethod(returnType, new DISPID(dispId), fullLengthArgs);
238239
} else {
239240
String methName = this.getMethodName(method, meth);
240-
return this.invokeMethod(returnType, methName, args);
241+
return this.invokeMethod(returnType, methName, fullLengthArgs);
241242
}
242243
}
243244

@@ -401,6 +402,21 @@ public <T> T invokeMethod(Class<T> returnType, DISPID dispID, Object... args) {
401402
return (T) Convert.toJavaObject(result, returnType, factory, false, true);
402403
}
403404

405+
private Object[] unfoldWhenVarargs(java.lang.reflect.Method method, Object[] argParams) {
406+
if (null == argParams) {
407+
return null;
408+
}
409+
if (argParams.length == 0 || !method.isVarArgs() || !(argParams[argParams.length - 1] instanceof Object[])) {
410+
return argParams;
411+
}
412+
// when last parameter is Object[] -> unfold the ellipsis:
413+
Object[] varargs = (Object[]) argParams[argParams.length - 1];
414+
Object[] args = new Object[argParams.length - 1 + varargs.length];
415+
System.arraycopy(argParams, 0, args, 0, argParams.length - 1);
416+
System.arraycopy(varargs, 0, args, argParams.length - 1, varargs.length);
417+
return args;
418+
}
419+
404420
@Override
405421
public <T> T queryInterface(Class<T> comInterface) throws COMException {
406422
assert COMUtils.comIsInitialized() : "COM not initialized";

contrib/platform/test/com/sun/jna/platform/win32/COM/util/ProxyObject_Test.java

+71-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
import com.sun.jna.Pointer;
1616
import static org.junit.Assert.*;
1717

18+
import java.io.File;
19+
1820
import org.junit.After;
1921
import org.junit.Before;
2022
import org.junit.Test;
@@ -41,8 +43,53 @@ interface Application extends IUnknown {
4143

4244
@ComMethod
4345
void Quit(boolean SaveChanges, Object OriginalFormat, Boolean RouteDocument);
46+
47+
@ComMethod
48+
public void Quit(Object... someArgs);
49+
50+
@ComMethod(dispId = 0x00000183)
51+
public float PointsToPixels(float points, Object... someArgs);
52+
53+
@ComProperty(dispId = 0x00000006)
54+
public Documents getDocuments();
4455
}
45-
56+
57+
@ComInterface(iid = "{0002096C-0000-0000-C000-000000000046}")
58+
public interface Documents extends IDispatch {
59+
@ComMethod
60+
public _Document Add(Object template, Object newTemplate, Object documentType, Object visible);
61+
62+
@ComMethod
63+
public _Document Add(Object... someArgs);
64+
}
65+
66+
@ComInterface(iid = "{0002096B-0000-0000-C000-000000000046}")
67+
public interface _Document extends IDispatch {
68+
@ComMethod
69+
public void SaveAs(Object fileName, Object fileFormat, Object lockComments, Object password,
70+
Object addToRecentFiles, Object writePassword, Object readOnlyRecommended, Object embedTrueTypeFonts,
71+
Object saveNativePictureFormat, Object saveFormsData, Object saveAsAOCELetter, Object encoding,
72+
Object insertLineBreaks, Object allowSubstitutions, Object lineEnding, Object addBiDiMarks);
73+
74+
@ComMethod
75+
public void SaveAs(Object... someArgs);
76+
}
77+
78+
public enum WdSaveFormat implements IComEnum {
79+
wdFormatDocument(0), wdFormatText(2), wdFormatRTF(6), wdFormatHTML(8), wdFormatPDF(17);
80+
81+
private long _value;
82+
83+
private WdSaveFormat(long value) {
84+
_value = value;
85+
}
86+
87+
@Override
88+
public long getValue() {
89+
return _value;
90+
}
91+
}
92+
4693
@ComObject(progId="Word.Application")
4794
interface MsWordApp extends Application {
4895
}
@@ -116,4 +163,27 @@ public void accessWhilstDisposing() {
116163

117164
}
118165

166+
@Test
167+
public void testVarargsCallWithoutVarargParameter() {
168+
MsWordApp comObj = this.factory.createObject(MsWordApp.class);
169+
170+
// call must work without exception:
171+
float f = comObj.PointsToPixels(25.3f);
172+
comObj.Quit();
173+
}
174+
175+
@Test
176+
public void testVarargsCallWithParameter() {
177+
MsWordApp comObj = this.factory.createObject(MsWordApp.class);
178+
179+
Documents documents = comObj.getDocuments();
180+
_Document myDocument = documents.Add();
181+
182+
String path = new File(".").getAbsolutePath();
183+
myDocument.SaveAs(path + "\\abcdefg", WdSaveFormat.wdFormatPDF);
184+
comObj.Quit();
185+
186+
boolean wasDeleted = new File("abcdefg.pdf").delete();
187+
assertTrue(wasDeleted);
188+
}
119189
}

0 commit comments

Comments
 (0)