'GraalVM how to return an array from a method to the guest language?
I'm playing around with GraalVM (Truffle) in OpenJDK 17, and would like to know what the correct way is to return values to the guest language from method calls? Right now I'm struggling with passing a String[] array back.
Exmaple:
Java (host)
class Services
{
Value message;
@HostAccess.Export
public String[] getArrayString()
{
return new String[]{"s1", "s2", "s3"};
}
@HostAccess.Export
public void setMessage( Value v )
{
message = v;
message.pin();
}
}
...
String jsScript = " ... " // see below
try ( Context context = Context.newBuilder().allowHostAccess(HostAccess.SCOPED).build() )
{
Services s = new Services();
context.getBindings("js").putMember("services", s);
context.eval("js", jsScript);
}
JavaScript (guest)
var a = services.getArrayString();
b = '';
for ( var c in a ) b += c;
services.setMessage('' + a + ' // ' + b)
The final message value is "[object Object] // " (b is blank), however I expected something like "[object Object] // s1s2s3".
I've also tried the return types Object[] and ArrayList<String>. I'm not sure why I can't access the elements of the array, either I'm not passing the array back correctly, or I'm not accessing it correctly within the JavaScript script. The examples I've found in the GraalVM docs are always about passing values directly from the host to the guest, but I'd like to do it via a method call - how is that done?
Solution 1:[1]
I've finally found a way to pass an array from the host to the guest - using ProxyArray.
Reading through the Graalvm documentation and experimenting with the very primative examples they provide, I came up with the following changes to my Services class:
ArrayList<String> array = new ArrayList<String>();
@HostAccess.Export
public void prepareList()
{
array.add("s1");
array.add("s2");
array.add("s3");
}
@HostAccess.Export
public ProxyArray getArray()
{
return new ProxyArray() {
@Override
public Object get( long index )
{
return array.get((int)index);
}
@Override
public void set( long index, Value value )
{
// TODO Auto-generated method stub
}
@Override
public long getSize()
{
return array.size();
}
};
}
And finally the guest call looks like this:
services.prepareList();
var a = services.getArray();
b = '';
for ( i = 0; i < a.length; i++ ) b += a[i];
services.setMessage('' + a + ' // ' + b)
And the value of the message is then as expected "[object Object] // s1s2s3"
Hope someone finds this useful ... and if you have a better way of returning objects (Array, Hashtable, whatever) post your answers here - thanks.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
