Explicit foreign operations: `std:interop`
Canonical source:
docs/guide/library/interop.mdat locked revisione99b712ecf658a527b1fe82c8beba2c1286d8dc9. This rendered page is non-normative; the applicable Protos specification remains authoritative.
std:interop provides four explicit operations on foreign values — values
that a foreign provider handed to your program, such as a foreign module facade
or a raw foreign reference. It is the escape hatch for the cases ordinary
Protos syntax deliberately does not cover.
Interop: import("std:interop")The module is a single source,
protos/lib/interop.protos. Its normative
owner is “Relation to explicit interoperability” in
spec/semantics/VALUES_AND_COLLECTIONS.md.
For the overall foreign-value model, start with
Foreign interoperability.
Operations
Section titled “Operations”| Operation | Effect |
|---|---|
Interop.invoke(target, ...arguments) |
Executes the foreign target and answers its admitted result |
Interop.instantiate(target, ...arguments) |
Instantiates the foreign target and answers its admitted result |
Interop.readMember(target, name) |
Reads foreign member name (a String) |
Interop.writeMember(target, name, value) |
Writes foreign member name and answers exactly value |
Why they exist:
invokeandinstantiateare distinct even when a target supports both; ordinarycalldoes not choose between them for you.readMemberbypasses ordinary Protos lookup for one operation, so a foreign member namedcall,at,each,==, orhashis reachable.writeMemberis the only way to write a foreign member: ordinarytarget.name = valuenever writes to the foreign object.
Interop: import("std:interop")Remote: import("example:service") // hypothetical scheme of a loaded provider
Interop.readMember(Remote, "hash") // the foreign member, not Protos `hash`Interop.writeMember(Remote, "timeout", 30)Importing std:interop opens no provider session, performs no discovery, and
grants no authority. It does not change how ordinary syntax behaves on foreign
values.
Failures
Section titled “Failures”- A failure detected before the foreign operation is entered signals an
ordinary Error: the target is not foreign, wrong arity, a
namethat is not a String, an operation the target does not support, an argument that cannot be projected losslessly, or a closed session. For example,Interop.invoke(42)signals an Error. - A failure after entry signals a fresh
ForeignErrorwith only safe slots (language,operation,category,foreignCategory,message,cause); host exceptions and stack traces are never exposed.
A Closure passed as an argument crosses only as a synchronous callback scoped to
that one operation. Callbacks do not cross the public external provider SPI at
this revision, so a provider loaded with --foreign-provider-path cannot call
back into Protos.
Where foreign values come from
Section titled “Where foreign values come from”No foreign provider ships inside the Protos distribution. To obtain foreign values today you load an external provider JAR on the portable JVM CLI:
protos --foreign-provider-path provider.jar main.protosSee Writing and registering an external provider
and the java: provider fixture. The Java
standard-library fixture uses the java: scheme; jdk: is not a provider
scheme and is not an alias for it.
JVM and Native
Section titled “JVM and Native”| Distribution | std:interop |
|---|---|
| Portable JVM | Module available; operates on values from providers loaded with --foreign-provider-path |
| Native Linux x86_64 | Part of the shipped Standard Library, but the Native CLI cannot load external providers, so there are no foreign values for it to act on |
Java embedding with a standard Polyglot Context is a portable-JVM feature
only, and even there no public API registers foreign providers; see
Embedding Protos in a Java application.