Bug 93652 - [OLE] Support of VARIANTs of type VT_ARRAY in org.eclipse.swt.ole.win32
Summary: [OLE] Support of VARIANTs of type VT_ARRAY in org.eclipse.swt.ole.win32
Status: CLOSED WONTFIX
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 3.1   Edit
Hardware: PC Windows XP
: P3 normal with 3 votes (vote)
Target Milestone: ---   Edit
Assignee: Platform-SWT-Inbox CLA
QA Contact: Felipe Heidrich CLA
URL:
Whiteboard: stalebug
Keywords: triaged
: 10977 (view as bug list)
Depends on:
Blocks:
 
Reported: 2005-05-04 10:30 EDT by Bertrand Cormier CLA
Modified: 2020-05-30 11:23 EDT (History)
7 users (show)

See Also:


Attachments
A modified Variant.java file which handles variants of type SafeArray. (27.14 KB, text/plain)
2005-05-11 10:08 EDT, Bertrand Cormier CLA
no flags Details
Modified (up-to-date) version of the patch, in-line with SWT 3.6 (34.62 KB, application/octet-stream)
2010-07-13 15:04 EDT, Christopher Deckers CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Bertrand Cormier CLA 2005-05-04 10:30:37 EDT
I've got a variant of type VT_VARIANT | VT_ARRAY. 
VT_ARRAY means that there is a pointer to the array in the data, 
Unfortunately SWT Variant does not support VT_ARRAY and does not give
access to that pointer.  In Variant.setData it would need to add code 
similar to the code for VT_BYREF to save the pointer in a field.
Comment 1 Bertrand Cormier CLA 2005-05-11 10:08:30 EDT
Created attachment 20964 [details]
A modified Variant.java file which handles variants of type SafeArray.

All the modifications made to the original Variant.java file have been tagged
with "Added by BCO" / "End - Added by BCO".
 
This is how I use the class ('commandArray' being a 2D-array of simple 
type variants):

Variant.SafeArray safeArray = commandArray.getSafeArray();
int safeArrayPtr = 0;
for (int i=0; i<safeArray.rgsabound[0].cElements; i++) {
	safeArrayPtr = safeArray.pvData + 16*i;
    Variant var = new Variant();
    var.setSafeArray(safeArrayPtr);
    Variant.SafeArray safeArray2 = var.getSafeArray();
    int safeArrayPtr2 = 0;
    for (int j=0; j<safeArray2.rgsabound[0].cElements; j++) {
		safeArrayPtr2 = safeArray2.pvData + 16*j;
	Variant var2 = new Variant(safeArrayPtr2);
	var2.setSafeArray(safeArrayPtr2);
	if (var2.getType() == OLE.VT_BSTR)
		System.out.print("\"" + var2.getString() + "\" ");
	else if (var2.getType() == OLE.VT_I4)
		System.out.print(var2.getInt() + " ");
	else if (var2.getType() == OLE.VT_BOOL)
		System.out.print(var2.getBoolean() + " ");
	else
		System.err.print("<type=" + var2.getType() + "> ");   
    }
	System.out.println(); // carriage return
}
Comment 2 Bertrand Cormier CLA 2005-05-11 10:10:38 EDT
Find attached a proposition to handle variants of type SafeArray 
(VT_ARRAY|VT_*).
Comment 3 Veronika Irvine CLA 2005-05-13 12:19:04 EDT
Bertrand, thank you for the patch.  Unfortunately, the solution requires new 
API and 1) we are API frozen so I would need to get the Eclipse API review 
committee to grant permission for the change and 2) this is not the way I 
would like to see the API of Variant evolve.

Regarding 2, I do not want to expose a class like SafeArray and 
SafeArrayBounds.  I would prefer to have API like Variant.get/setIntArray(), 
Variant.get/setStringArray() or perhaps more generically 
Variant.get/setVariantArray().
Comment 4 Roland Tepp CLA 2005-06-03 10:26:28 EDT
Hello,

Is this going to be implementad anytime soon?

I really need Browser widget that allows making POST requests and SAFEARRAY
implementation (what ever it would look like) is needed to implement it.
Comment 5 Veronika Irvine CLA 2005-06-03 10:52:48 EDT
Roland, I think what you are asking for is addressed in the following Snippet:

http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclip
se/swt/snippets/Snippet186.java?rev=HEAD&content-type=text/vnd.viewcvs-markup

What Bertrand has requested is a bit different - it is a VT_ARRAY that is not 
accessed by reference.
Comment 6 Jens Vagts CLA 2005-12-20 04:57:07 EST
I would love to have the safearray support directly in the variant! Currently I'm using the (modified) code snippet, but that should not be the final solution for a product. Primary I need to transfer byte arrays.
Comment 7 Felipe Heidrich CLA 2009-08-13 11:27:17 EDT
Your bug has been moved to triage, visit http://www.eclipse.org/swt/triage.php for more info.
Comment 8 Felipe Heidrich CLA 2009-08-13 11:30:32 EDT
see bug 68194 comment 15, the patch in there implements support for returning
or passing a safearray of IDispatch interfaces.
Comment 9 Felipe Heidrich CLA 2009-08-19 12:33:33 EDT
*** Bug 10977 has been marked as a duplicate of this bug. ***
Comment 10 Christopher Deckers CLA 2010-06-29 12:52:23 EDT
(In reply to comment #3)
> 2) this is not the way I 
> would like to see the API of Variant evolve.
> 
> Regarding 2, I do not want to expose a class like SafeArray and 
> SafeArrayBounds.  I would prefer to have API like Variant.get/setIntArray(), 
> Variant.get/setStringArray() or perhaps more generically 
> Variant.get/setVariantArray().

Would such API allow multi-dimensional arrays? Because I have an Ole component which has such API and I am stumbling on this bug!

Would it be possible to get this in for the next version? I would definitely go for a milestone release and provide feedback if something gets there.

Cheers,
-Christopher
Comment 11 Christopher Deckers CLA 2010-07-13 15:04:39 EDT
Created attachment 174211 [details]
Modified (up-to-date) version of the patch, in-line with SWT 3.6

I ported the changes to the current version of SWT (3.6).

The SafeArray class seems to point to the right data, but extracting that data is a pain.
My test case is simply Excel, where I try to get the values of a Range. This is in the form of an array of variants, which themselves are BSTRs in my test case. I believe these could be of other types.

Variant arrayVariant = //get property from Range.
SafeArray safeArray = arrayVariant.getSafeArray();
int safeArrayPtr = safeArray.pvData;

I empirically found that:
String s = new Variant(safeArrayPtr + 8 + x*16, (short)(COM.VT_BYREF | COM.VT_BSTR)).getString())
where x = 1..4 for a 2D array of 2x2.

I understand how to iterate for this kind of data, but I harcoded the BSTR type and I have no clue where I should read that VT type. It seems fFeature in SafeArray has the flag "FADF_HAVEVARTYPE" in my case, which means that "An array that has a VT type. When set, there will be a VT tag at negative offset 4 in the array descriptor that specifies the element type.". Having to walk negatively depending on obscure flags (and I tried without finding the type I was looking for) is insane.

I also read this:
"You should not attempt to manipulate a safearray or access an element manually; you should instead either use the API functions, or much better yet use the helper class CComSafeArray."
Looking at the complexity of walking thoses structure manually, I think exposing the functions of one of these libraries is the way to go.

Maybe the SafeArray class could hold the SafeArray structure (as it is now), but have methods that belong to one of these helper libraries, with type conversion where a VARIANT is internally returned for example.
Comment 12 Felipe Heidrich CLA 2010-07-14 15:52:50 EDT
I don't think the code in the patch is all that helpful, it reads the header information from the memory buffer (and makes it easily accessible by putting it in fields) but it doesn't provide any help to read the data (string, bytes, whatever is store in the array) from the array.

In order to become an API the solution has the be complete (at least make easy to access the data in the array for primite types).
Comment 13 Christopher Deckers CLA 2010-07-14 17:46:02 EDT
> In order to become an API the solution has the be complete (at least make easy
> to access the data in the array for primite types).

Yes I fully agree, but there exists such API as native libraries, and I don't think it is a good idea to re-write them in terms of low level calls. Everything I read basically said to not read by hand but use those libraries. I think what is necessary is simply to expose the methods of those native libaries in the SWT Java API.
In such a case, we need to see a SafeArray class, which is actually the class to be manipulated by those new library-copied methods. It also makes sense to have a getter on the Variant instead of having to manipulate by hand a SAFEARRAY struct.
Comment 14 Felipe Heidrich CLA 2010-07-15 09:13:57 EDT
Is this library part of Windows ? Or has to be installed from third-parts ?

If it is part of Windows, we can use it to implement our API.
For example, we would add a Variant#getStringArray() which internally uses this library to do all the low level work returning a nice java String[] array to the caller.
Comment 15 Christopher Deckers CLA 2010-07-15 10:12:01 EDT
> Is this library part of Windows ? Or has to be installed from third-parts ?

I am not a Windows developer so I don't really know what is part of Windows or not.

What I could find are these, there may be more:

CComSafeArray Class (ATL)
http://msdn.microsoft.com/en-us/library/3xzbsee8%28v=VS.80%29.aspx

Array Manipulation Functions [Automation]
http://msdn.microsoft.com/en-us/library/ms221145.aspx

Is one of them a good candidate? If the first one is, then it looks like the way to go.

Here is an examples of a Java API mapping for SafeArray (in Jacob), if it can help give ideas:
http://jarvana.com/jarvana/view/net/sf/jacob-project/jacob/1.14.3/jacob-1.14.3-javadoc.jar!/api/com/jacob/com/SafeArray.html
Comment 16 Felipe Heidrich CLA 2010-07-15 12:42:51 EDT
I would avoid the first one as it uses ATL.

The second one is fine. We should be able to use it, that said, you already did most of the job using low-level calls (meaning, we already know how to do that).
It just need the code to get the elements (it should not be too bad, maybe easier than leraning how to use SafeArray* calls).


As far as an API goes, maybe all we need to add is a getArray(), setArray()  methods to be used when type == VT_ARRAY
This would be similar to type == VT_BSTR, when getString/setString are used.
(should also add constructor taking an array to consistent with all other types)

getArray() would return a array of Variant objets. A Variant element of array can be another array (multi dimensional arrays).

That is how I would try to implement this API.
I know SafeArrays in COM and java arrays are not the same thing (SafeArrays have lower bounds/upper bounds and other things). I think it would be possible to map from one to another.
Comment 17 Christopher Deckers CLA 2010-07-15 14:17:22 EDT
> I would avoid the first one as it uses ATL.

You are the judge, as I said my knowledge is very limited and I have to say I really struggle to find the little information I communicated.

> The second one is fine.

> getArray() would return a array of Variant objets. A Variant element of array
> can be another array (multi dimensional arrays).

Well, a SafeArray can be an array of any type and, if I am not mistaken, of type by ref or not. I only tried with an array of Variant (by ref) so there is probably a bit more to do. It may not be that much as I guess reading a long or a String is probably similar to what the Variant is doing.

> I know SafeArrays in COM and java arrays are not the same thing (SafeArrays
> have lower bounds/upper bounds and other things).

I think I read somewhere that lower bounds are always 0 in C, only VB may use different values (even negative!)
Comment 18 Christopher Deckers CLA 2010-07-15 14:43:11 EDT
> Well, a SafeArray can be an array of any type and, if I am not mistaken, of
> type by ref or not.

Explorer uses an array of VT_UI1 as demonstrated in Snippet 186 (which ought to be converted to a more friendly API), and Excel ranges are arrays of VT_VARIANT (which themselves are of BTSTR, though I failed to find where that type is without using helper libraries). I think these are good first test cases.

If there is any progress and if there is something to test, let me know and I would try it out with a nightly build. And of course if I can help progress on that issue somehow, please let me know how.
Comment 19 Felipe Heidrich CLA 2010-07-15 15:35:41 EDT
(In reply to comment #18)
> If there is any progress and if there is something to test, let me know and I
> would try it out with a nightly build. And of course if I can help progress on
> that issue somehow, please let me know how.

Right now I don't have time to work on OLE as I am (very) busy working on something else. I was hoping for someone from the community to collaborate with a patch which I would review and release.
Comment 20 Christopher Deckers CLA 2010-07-15 15:45:40 EDT
> I was hoping for someone from the community to collaborate with
> a patch which I would review and release.

Yes, which is why I tried to contribute but fiddling with existing SWT mapped APIs is not enough and my Windows API and C knowledge is too rusty.

I just hope it does not mean this feature is back to an endless sleep, because it is the missing piece for proper OLE support (in which my interface generator could be of great use for example).
Comment 21 Leo Ufimtsev CLA 2017-08-03 12:34:36 EDT
This is a one-off bulk update. (The last one in the triage migration).

Moving bugs from swt-triaged@eclipse to platform-swt-inbox@eclipse.org and adding "triaged" keyword as per new triage process:
https://wiki.eclipse.org/SWT/Devel/Triage

See Bug 518478 for details.

Tag for notification/mail filters:
@TriageBulkUpdate
Comment 22 Eclipse Genie CLA 2020-05-30 11:23:04 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. As such, we're closing this bug.

If you have further information on the current state of the bug, please add it and reopen this bug. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.