5

I am using Jacob to call VBA COM interfaces in software. I need to call a Sub that has an output parameter, that is not of canonical type (int, String, etc.) but of some dedicated interface declared in .tlb that are brought with this software. Here is the

Sub GetMaterialOnBody (Body iBody, Material oMaterial)

So I tried many declarations and initializations for the output parameter material in the call, I get various errors and cannot seem to find the proper way to do.

Variant material = new Variant (null, false);
Dispatch.invoke(materialManager.getDispatch(), "GetMaterialOnBody", Dispatch.Method, new Object[] {hybridBody, material}, new int[1]);

but got

com.jacob.com.ComFailException: A COM exception has been encountered:
At Invoke of: GetMaterialOnBody
Description: Type mismatch.

Then I tried to call .getDispatch() on material

Variant material = new Variant (null, false);
Dispatch.invoke(materialManager.getDispatch(), "GetMaterialOnBody", Dispatch.Method, new Object[] {hybridBody, material.getDispatch()}, new int[1]);

but got

java.lang.IllegalStateException: getDispatch() only legal on Variants of type VariantDispatch, not 0

So I tried

Variant material = new Variant (null, false);
material.putNothing();
Dispatch.invoke(materialManager.getDispatch(), "GetMaterialOnBody", Dispatch.Method, new Object[] {hybridBody, material.getDispatch()}, new int[1]);

but got

com.jacob.com.ComFailException: putObject failed
at com.jacob.com.Variant.putVariantDispatch(Native Method) ~[jacob-1.14.3.jar:na]
at com.jacob.com.Variant.putDispatch(Variant.java:1341) ~[jacob-1.14.3.jar:na]

I tried different solutions, including using Ref, etc. I am a bit lost on how exactly we have to initialize a variant/dispatch to pass as an output parameter in a Sub.

Does anyone have any clue on how to do that? The closes resources I found were handling String/Integer and not object.

This old question might be related (but obviously no answer): https://community.oracle.com/tech/developers/discussion/1548970/jacob-out-parameters-refs-in-jni

I have open a question on the jacob github https://github.com/freemansoft/jacob-project/issues/23

Also I emailed the owner of the project on github and he said the project was dormant for some time already. As all the code is available I will take the time to compile and debug the native (C++) side in order to debug my case. I will update that question then.

Zzirconium
  • 431
  • 1
  • 10
  • 32
  • 1
    For grins, try reversing the order of the arguments. I remember calling Invoke() from C++ code and having to put parameters in reverse order of left to right. In fact, this says so: https://learn.microsoft.com/en-us/windows/win32/api/oaidl/nf-oaidl-idispatch-invoke – Joseph Willcoxson Mar 31 '21 at 15:28
  • OK I got it through by doing Variant material = new Variant (null, false); material.putNothing(); Dispatch.invoke(materialManager.getDispatch(), "GetMaterialOnBody", Dispatch.Method, new Object[] {hybridBody, material}, new int[1]); However it seems that the variant material has not been set after invoke – Zzirconium Feb 04 '22 at 13:40

1 Answers1

0

if that is output parameter, shouldn't it be 'ByRef' ?

Sub GetMaterialOnBody (Body iBody, ByRef Material oMaterial)

In your case probably GetMaterialOnBody sub is expected to fill in internals of oMaterial object, not to set reference to it? Then just create an empty Material object and pass to the sub

Andrey
  • 1,752
  • 18
  • 17
  • Hey thanks for your proposal, indeed that's a ByRef. I did already try to create an empty material (that's the putNothing call) but it was not populated when the call returned. – Zzirconium Feb 11 '22 at 09:34