0
# Interoperability
1
2
Language interoperability framework that enables seamless interaction between different programming languages in GraalVM through the InteropLibrary protocol and polyglot bindings.
3
4
## Capabilities
5
6
### InteropLibrary
7
8
Core interoperability protocol that provides language-neutral operations for reading, writing, executing, and type checking of foreign objects.
9
10
```java { .api }
11
/**
12
* Library for interoperating with foreign objects from different languages
13
* Main protocol for cross-language object interaction
14
*/
15
@ExportLibrary(value = InteropLibrary.class, delegateTo = "delegate")
16
public abstract class InteropLibrary extends Library {
17
/** Returns the singleton interop library for uncached usage */
18
public static InteropLibrary getUncached();
19
20
/** Returns a cached interop library instance for the given object */
21
public static InteropLibrary getUncached(Object receiver);
22
23
// === Object Identity and Null Checks ===
24
25
/** Checks if the object represents null */
26
public boolean isNull(Object receiver);
27
28
/** Checks if the object is identical to another object */
29
public boolean isIdentical(Object receiver, Object other, InteropLibrary otherInterop);
30
31
/** Returns the identity hash code */
32
public int identityHashCode(Object receiver);
33
34
// === Boolean Operations ===
35
36
/** Checks if the object represents a boolean value */
37
public boolean isBoolean(Object receiver);
38
39
/** Returns the boolean value */
40
public boolean asBoolean(Object receiver) throws UnsupportedMessageException;
41
42
// === String Operations ===
43
44
/** Checks if the object represents a string */
45
public boolean isString(Object receiver);
46
47
/** Returns the string value */
48
public String asString(Object receiver) throws UnsupportedMessageException;
49
50
// === Number Operations ===
51
52
/** Checks if the object represents a number */
53
public boolean isNumber(Object receiver);
54
55
/** Checks if the number fits in a specific type */
56
public boolean fitsInByte(Object receiver);
57
public boolean fitsInShort(Object receiver);
58
public boolean fitsInInt(Object receiver);
59
public boolean fitsInLong(Object receiver);
60
public boolean fitsInFloat(Object receiver);
61
public boolean fitsInDouble(Object receiver);
62
63
/** Converts the number to a specific type */
64
public byte asByte(Object receiver) throws UnsupportedMessageException;
65
public short asShort(Object receiver) throws UnsupportedMessageException;
66
public int asInt(Object receiver) throws UnsupportedMessageException;
67
public long asLong(Object receiver) throws UnsupportedMessageException;
68
public float asFloat(Object receiver) throws UnsupportedMessageException;
69
public double asDouble(Object receiver) throws UnsupportedMessageException;
70
71
// === Array Operations ===
72
73
/** Checks if the object has array elements */
74
public boolean hasArrayElements(Object receiver);
75
76
/** Returns the size of the array */
77
public long getArraySize(Object receiver) throws UnsupportedMessageException;
78
79
/** Checks if an array index is readable */
80
public boolean isArrayElementReadable(Object receiver, long index);
81
82
/** Reads an array element */
83
public Object readArrayElement(Object receiver, long index)
84
throws UnsupportedMessageException, InvalidArrayIndexException;
85
86
/** Checks if an array index is writable */
87
public boolean isArrayElementWritable(Object receiver, long index);
88
89
/** Writes an array element */
90
public void writeArrayElement(Object receiver, long index, Object value)
91
throws UnsupportedMessageException, InvalidArrayIndexException, UnsupportedTypeException;
92
93
// === Member Operations ===
94
95
/** Checks if the object has members (properties) */
96
public boolean hasMembers(Object receiver);
97
98
/** Returns the list of member keys */
99
public Object getMembers(Object receiver, boolean includeInternal) throws UnsupportedMessageException;
100
101
/** Checks if a member is readable */
102
public boolean isMemberReadable(Object receiver, String member);
103
104
/** Reads a member value */
105
public Object readMember(Object receiver, String member)
106
throws UnsupportedMessageException, UnknownIdentifierException;
107
108
/** Checks if a member is writable */
109
public boolean isMemberWritable(Object receiver, String member);
110
111
/** Writes a member value */
112
public void writeMember(Object receiver, String member, Object value)
113
throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException;
114
115
/** Checks if a member is removable */
116
public boolean isMemberRemovable(Object receiver, String member);
117
118
/** Removes a member */
119
public void removeMember(Object receiver, String member)
120
throws UnsupportedMessageException, UnknownIdentifierException;
121
122
// === Execution Operations ===
123
124
/** Checks if the object is executable */
125
public boolean isExecutable(Object receiver);
126
127
/** Executes the object as a function */
128
public Object execute(Object receiver, Object... arguments)
129
throws UnsupportedMessageException, ArityException, UnsupportedTypeException;
130
131
/** Checks if the object is instantiable */
132
public boolean isInstantiable(Object receiver);
133
134
/** Instantiates the object as a constructor */
135
public Object instantiate(Object receiver, Object... arguments)
136
throws UnsupportedMessageException, ArityException, UnsupportedTypeException;
137
}
138
```
139
140
**Usage Examples:**
141
142
```java
143
import com.oracle.truffle.api.interop.InteropLibrary;
144
import com.oracle.truffle.api.interop.UnsupportedMessageException;
145
146
public Object interopExample(Object foreignObject) {
147
InteropLibrary interop = InteropLibrary.getUncached(foreignObject);
148
149
try {
150
// Check and read properties
151
if (interop.hasMembers(foreignObject)) {
152
Object members = interop.getMembers(foreignObject, false);
153
154
if (interop.isMemberReadable(foreignObject, "name")) {
155
Object name = interop.readMember(foreignObject, "name");
156
if (interop.isString(name)) {
157
return interop.asString(name);
158
}
159
}
160
}
161
162
// Check and call as function
163
if (interop.isExecutable(foreignObject)) {
164
return interop.execute(foreignObject, "arg1", 42);
165
}
166
167
// Array access
168
if (interop.hasArrayElements(foreignObject)) {
169
long size = interop.getArraySize(foreignObject);
170
if (size > 0 && interop.isArrayElementReadable(foreignObject, 0)) {
171
return interop.readArrayElement(foreignObject, 0);
172
}
173
}
174
175
} catch (UnsupportedMessageException | InvalidArrayIndexException | UnknownIdentifierException e) {
176
// Handle interop errors
177
return null;
178
}
179
180
return foreignObject;
181
}
182
```
183
184
### TruffleObject
185
186
Marker interface that identifies objects as Truffle interoperability objects.
187
188
```java { .api }
189
/**
190
* Marker interface for objects that participate in Truffle interoperability
191
* Objects implementing this interface can be passed between languages
192
*/
193
public interface TruffleObject {
194
// Marker interface - no methods
195
}
196
```
197
198
### Exception Handling
199
200
Specialized exceptions for interoperability error conditions.
201
202
```java { .api }
203
/**
204
* Exception thrown when an interop message is not supported
205
*/
206
public final class UnsupportedMessageException extends InteropException {
207
/** Creates exception for unsupported message */
208
public static UnsupportedMessageException create();
209
}
210
211
/**
212
* Exception thrown when array index is invalid
213
*/
214
public final class InvalidArrayIndexException extends InteropException {
215
/** Creates exception for invalid array index */
216
public static InvalidArrayIndexException create(long invalidIndex);
217
218
/** Returns the invalid index */
219
public long getInvalidIndex();
220
}
221
222
/**
223
* Exception thrown when identifier is unknown
224
*/
225
public final class UnknownIdentifierException extends InteropException {
226
/** Creates exception for unknown identifier */
227
public static UnknownIdentifierException create(String unknownIdentifier);
228
229
/** Returns the unknown identifier */
230
public String getUnknownIdentifier();
231
}
232
233
/**
234
* Exception thrown when type is not supported for operation
235
*/
236
public final class UnsupportedTypeException extends InteropException {
237
/** Creates exception for unsupported type */
238
public static UnsupportedTypeException create(Object[] suppliedValues);
239
240
/** Creates exception for unsupported type with message */
241
public static UnsupportedTypeException create(Object[] suppliedValues, String hint);
242
243
/** Returns the supplied values that caused the error */
244
public Object[] getSuppliedValues();
245
}
246
247
/**
248
* Exception thrown when wrong number of arguments provided
249
*/
250
public final class ArityException extends InteropException {
251
/** Creates exception for wrong arity */
252
public static ArityException create(int expectedMinArity, int expectedMaxArity, int actualArity);
253
254
/** Returns the expected minimum arity */
255
public int getExpectedMinArity();
256
257
/** Returns the expected maximum arity */
258
public int getExpectedMaxArity();
259
260
/** Returns the actual arity provided */
261
public int getActualArity();
262
}
263
```
264
265
### Message Resolution
266
267
System for optimizing interop message dispatch through specialized nodes.
268
269
```java { .api }
270
/**
271
* Base class for interop message resolution
272
*/
273
public abstract class Message {
274
/** Returns the message name */
275
public abstract String getSimpleName();
276
277
/** Creates a message node for this message */
278
public abstract InteropNode createNode();
279
280
// Predefined message constants
281
public static final Message IS_NULL = createMessage("IS_NULL");
282
public static final Message IS_EXECUTABLE = createMessage("IS_EXECUTABLE");
283
public static final Message EXECUTE = createMessage("EXECUTE");
284
public static final Message READ = createMessage("READ");
285
public static final Message WRITE = createMessage("WRITE");
286
// ... additional message constants
287
}
288
289
/**
290
* Specialized node for executing interop messages
291
*/
292
public abstract class InteropNode extends Node {
293
/** Executes the interop message */
294
public abstract Object execute(Object receiver, Object[] arguments);
295
296
/** Creates a node for the given message */
297
public static InteropNode create(Message message);
298
}
299
```
300
301
## Common Types
302
303
```java { .api }
304
public abstract class InteropException extends Exception {
305
/** Base class for all interop-related exceptions */
306
}
307
308
public interface Library {
309
/** Base interface for all Truffle library protocols */
310
311
/** Accepts a visitor for library introspection */
312
public boolean accepts(Object receiver);
313
}
314
315
@Target({ElementType.TYPE})
316
@Retention(RetentionPolicy.RUNTIME)
317
public @interface ExportLibrary {
318
/** Annotation for exporting library implementations */
319
Class<? extends Library> value();
320
String delegateTo() default "";
321
int priority() default 0;
322
}
323
```
324
325
**Usage Examples:**
326
327
```java
328
// Implementing interop for custom objects
329
@ExportLibrary(InteropLibrary.class)
330
public class MyLanguageObject implements TruffleObject {
331
private final Map<String, Object> members = new HashMap<>();
332
333
@ExportMessage
334
public boolean hasMembers() {
335
return true;
336
}
337
338
@ExportMessage
339
public Object getMembers(boolean includeInternal) {
340
return new KeysArray(members.keySet().toArray(new String[0]));
341
}
342
343
@ExportMessage
344
public boolean isMemberReadable(String member) {
345
return members.containsKey(member);
346
}
347
348
@ExportMessage
349
public Object readMember(String member) throws UnknownIdentifierException {
350
if (!members.containsKey(member)) {
351
throw UnknownIdentifierException.create(member);
352
}
353
return members.get(member);
354
}
355
356
@ExportMessage
357
public boolean isMemberWritable(String member) {
358
return true;
359
}
360
361
@ExportMessage
362
public void writeMember(String member, Object value) {
363
members.put(member, value);
364
}
365
}
366
```