This loop works perfectly and prints the always same String on screen for several iterations, then suddenly throws an exception instead:
What do you need from me to further investigate? Again, on JACOB the same is rock solid, so I am pretty sure it is a bug in JNA.
--
You received this message because you are subscribed to the Google Groups "Java Native Access" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jna-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jna-users/7b3e0427-2260-43bc-8bfb-76f5ac4ac95bn%40googlegroups.com.
I would suggest doing everything you can to remove GC as a culprit. That would mean keeping hard references to anything involved in the operation (com object - including checking com object ref count, byref object, byref object pointer, etc).
* It fails not only for this single method, it apparently fails for all methods using VT_BSTR | VT_BYVAR variant parameters (non-byvar BSTR parameters do work pretty well).
--
You received this message because you are subscribed to the Google Groups "Java Native Access" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jna-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jna-users/5fb673a7-f8c7-4bd1-8923-114f34b01cb7n%40googlegroups.com.
IIUC then you assume that Java is reading 64 Bits of which 32 Bit are correctly sent by the client, but the other 32 Bit are pointing to random bits?
Precisely. Specifically the “ByReference” in JNA assumes the pointer size of the JVM on the JNA side (8 bytes). It is passing an 8-byte allocation to the COM server. Here is the allocation in the ByReference superclass that BSTRByReference extends:
protected ByReference(int dataSize) {
setPointer(new Memory(dataSize));
}
Of note, new Memory(size) does not clear those bytes so they can contain anything.
The COM server is faithfully filling 4 of those bytes.
Ultimately you shouldn’t be using BSTRByReference on a 64 bit JVM to map this data type. You can simply use an IntByReference to fetch the BSTR pointer, then use similar methods to the BSTR internals to fetch the string from that pointer value (get the length from pointer-4 and read it from pointer value).
--
You received this message because you are subscribed to the Google Groups "Java Native Access" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jna-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jna-users/32ccc10f-0e63-4c97-80bd-d02d18d82d2an%40googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jna-users/6959a1b0-29bd-4151-b269-c55c1cc43b83n%40googlegroups.com.
I see what you mean (you imply that the COM server actually is not compliant with Microsoft's rules, right?). I think this is what you propose:var ref = new VARIANT();
try {
ref.setVarType((short) VT_EMPTY);
tQsstatRemoteControl.qsstatVersion(handle, ref);
return ref.stringValue();
} finally {
OleAuto.INSTANCE.VariantClear(ref);
}Unfortunately ref.stringValue() always returns null then. If I instead use VT_EMPTY | BY_REF then JNA says: com.sun.jna.platform.win32.COM.COMInvokeException: An den Stub wurde ein Nullzeiger übergeben.(HRESULT: 800706f4)
Hence long in the TLB actually means "32 Bit" (I only have a 32 Bit TLB viewer so I cannot see whether a 64 Bit TLB viewer would actually learn anything from this truth).
I can confirm that the proposed code change indeed works like a charm! I modified all uses of BSTRByReference and and none of them is failing! 🚀 So apparently it seems that BSTRByReference(new BSTR()) is what the QS-STAT product expects us to do in the VT_BSTR | VT_BYREF case always, instead of simply BSTRBYReference(). So the question is: Is the difference between BSTRByReference(new BSTR()) and BSTRByReference() a bug in JNA, or is QS-STAT's expectation a violation of Microsoft's COM rules? 🤔
Anyways, we still have to find a solution for DoubleByReference always returning zero... 😉
Is the difference between BSTRByReference(new BSTR()) and BSTRByReference() a bug in JNA, or is QS-STAT's expectation a violation of Microsoft's COM rules
--
You received this message because you are subscribed to the Google Groups "Java Native Access" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jna-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jna-users/1ff347414dcbb85d91173dbc2f70a027203096c9.camel%40doppel-helix.eu.
Is the difference between BSTRByReference(new BSTR()) and BSTRByReference() a bug in JNA, or is QS-STAT's expectation a violation of Microsoft's COM rulesOption C: None of the above.JNA is not designed to use different pointer size than the operating system, and when interacting with another program it is up to the user to identify appropriate requirements for using its API; in fact, there's no way for JNA to know (without some help from you) that the COM server is 32-bit.
in any case, I would plea for zeroing the pointer in the BSTRByReference() default constructor, so in future people have no problem with BSTRByReference. :-)Regarding DoubleByReference, the use case is the Q-DAS function GetStatResult(handle, ..., BSTRByReference, DoubleByReference). I will post the full example tomorrow, the outcome was posted already in a separate thread. :-)
import com.sun.jna.platform.win32.Variant;
import com.sun.jna.platform.win32.Variant.VARIANT;
import com.sun.jna.ptr.DoubleByReference;
import com.sun.jna.ptr.FloatByReference;
public class FloatingpointVariantByRef {
public static void main(String[] args) {
FloatByReference floatResult = new FloatByReference();
DoubleByReference doubleResult = new DoubleByReference();
VARIANT v = new Variant.VARIANT();
v.setValue(Variant.VT_R4 |Variant.VT_BYREF, floatResult);
v.setValue(Variant.VT_R8 |Variant.VT_BYREF, doubleResult);
// Broken: Mismatch width
// v.setValue(Variant.VT_R4 |Variant.VT_BYREF, doubleResult);
// v.setValue(Variant.VT_R8 |Variant.VT_BYREF, floatResult);
}
}
What I do wonder about still is:
- Wouldn't it make sense to provide VARIANT(DoubleByReference) and VARIANT(int vt, Object value) constructors in a future JNA release, so one could leave out the subsequent setValue(int vt, Object value) call?
- Frankly spoken I have not quite understood why I have to manually tell JNA that a DoubleByReference actually should be a VT_R8 | VT_BYREF variant. Shouldn't it simply work out of the box to directly use DoubleByReference with an @ComMethod mapping? That would make things easier for application programmers.