Embedded CPython for the Vis sandbox: the whole Clojure API.
Vis runs sandbox Python — packages/vis-agent plus every shim in
resources/vis-shims/ — inside GraalPy today, which costs roughly 300 MB in
the native image. This library replaces that engine with a VENDORED CPython
reached through the JDK Foreign Function & Memory API over a first-party C
ABI (native/vispython), so the image carries a cdylib and an interpreter
tree beside it instead of a Truffle language inside it.
The bridge itself is JAVA — java/com/blockether/vispython/ — and this
namespace is a thin skin over it: Clojure argument shapes and keyword maps,
and nothing else. The reason is the native image the result is linked
into. Every downcall there is an invokeExact against a signature the
compiler knows and the host upcall's target is a static method found by name,
while the same code as interop is a reflective invocation an image only keeps
if somebody remembered to register it — the failure that does not show up in
a green JVM suite, only in a user's terminal. Java also owns the process
pinning, the upcall stub, the trust export and pip, because none of that is
made clearer by being written in Clojure.
Nothing links at build time. The library is resolved when it is first needed:
a path the host named through use-library! wins, then
VIS_PYTHON_NATIVE_PATH, then the classpath resource
prebuilds/<platform>/<file> a checkout has after a native build. The
published platform artifact is a release archive, not a jar, so a host that
unpacked one names it here. A failure anywhere below is a
VisPythonException whose .data
names the symbol, status, platform or path it is about.
Embedded CPython for the Vis sandbox: the whole Clojure API. Vis runs sandbox Python — `packages/vis-agent` plus every shim in `resources/vis-shims/` — inside GraalPy today, which costs roughly 300 MB in the native image. This library replaces that engine with a VENDORED CPython reached through the JDK Foreign Function & Memory API over a first-party C ABI (`native/vispython`), so the image carries a cdylib and an interpreter tree beside it instead of a Truffle language inside it. The bridge itself is JAVA — `java/com/blockether/vispython/` — and this namespace is a thin skin over it: Clojure argument shapes and keyword maps, and nothing else. The reason is the native image the result is linked into. Every downcall there is an `invokeExact` against a signature the compiler knows and the host upcall's target is a static method found by name, while the same code as interop is a reflective invocation an image only keeps if somebody remembered to register it — the failure that does not show up in a green JVM suite, only in a user's terminal. Java also owns the process pinning, the upcall stub, the trust export and pip, because none of that is made clearer by being written in Clojure. Nothing links at build time. The library is resolved when it is first needed: a path the host named through `use-library!` wins, then `VIS_PYTHON_NATIVE_PATH`, then the classpath resource `prebuilds/<platform>/<file>` a checkout has after a native build. The published platform artifact is a release archive, not a jar, so a host that unpacked one names it here. A failure anywhere below is a `VisPythonException` whose `.data` names the symbol, status, platform or path it is about.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |