ah, no, silly me...that's
java.library.path not the classpath.
the following works here:
$ java -Djava.library.path=. -jar target/clj-rust-0.1.0-SNAPSHOT-standalone.jar Hello from Clojure Hello, from Rust via Java!
...and we have a winner:
$ $GRAALVM_HOME/bin/native-image --initialize-at-build-time --no-server --no-fallback -jar target/clj-rust-0.1.0-SNAPSHOT-standalone.jar -H:Name=clojure-rust [clojure-rust:4219] classlist: 2,381.60 ms [clojure-rust:4219] (cap): 556.81 ms [clojure-rust:4219] setup: 1,474.61 ms [clojure-rust:4219] (typeflow): 4,127.76 ms [clojure-rust:4219] (objects): 3,696.51 ms [clojure-rust:4219] (features): 172.49 ms [clojure-rust:4219] analysis: 8,292.61 ms [clojure-rust:4219] (clinit): 147.99 ms [clojure-rust:4219] universe: 402.20 ms [clojure-rust:4219] (parse): 419.23 ms [clojure-rust:4219] (inline): 1,152.62 ms [clojure-rust:4219] (compile): 4,325.21 ms [clojure-rust:4219] compile: 6,282.71 ms [clojure-rust:4219] image: 617.56 ms [clojure-rust:4219] write: 121.88 ms [clojure-rust:4219] [total]: 19,781.71 ms $ time ./clojure-rust Hello from Clojure Hello, from Rust via Java! real 0m0.002s user 0m0.002s sys 0m0.000s
@retrogradeorbit it looks like your earlier work was helpful in getting this going, if i am not mistaken: https://github.com/retrogradeorbit/graal-native-image-jni 🙂
That looks useful indeed. I was able to figure it out using the README of the Rust jni lib. A gotcha was that loading the lib in the static block wasn’t working so I moved that after I found a comment on the GraalVM github
Next experiment: see if I can build sci as a native library and call that from Rust so have a scripting lang in Rust
ah, sorry for the misunderstanding 😅
nice idea for using sci via rust! perhaps even tree-sitter might eventually be hooked up to be used from jvm / graal using some of these bits.
I had seen Crispin’s repo before and I certainly would have reached for it if I would have been stuck
I’m still curious how @retrogradeorbit distributes dynlinked libs along with his native apps, because having them placed in a certain path by the user is a bit weird maybe
So, yes. I ended up loading them with
clojure.lang.RT/loadLibrary. It was the only way I could get the same code to work in leiningen, in a jar, and as a native binary, and in the test runner.
the other thing was bunding the lib in the resources and placing it on disk at runtime, and setting the java librarypath, which on some JVMs you cant reset after startup and have it stick, some you can trick the JVM into reloading, and some you can set!
luckily graal you can set at runtime. So I detect for it running as a graal native image, and set the value to the place I wrote my library if it is graal
I have been planning to make a minimal C clojure example but never got around to it
so this works to setup native-image: https://github.com/epiccastle/spire/blob/master/src/clj/spire/config.clj#L42-L52
this gets leiningen working: https://github.com/epiccastle/spire/blob/master/project.clj#L34-L36
and this loads the library, and works across both methods: https://github.com/epiccastle/spire/blob/master/src/clj/spire/core.clj#L33
haven't tested the jar build in a while... hopefully I didnt break it
I build/copy my compiled lib into project root dir, btw
thanks for sharing!
> Entry point methods must be static and may only have non-object parameters and return types – this includes Java primitives, but also Word types (including pointers). Whoops, I guess that makes it a lot harder to make sci useful within a language like Rust, C or Go
If I'd need an embedded scripting language Clojure still feels like a silly choice; given the option I'd probably embed Chicken Scheme
Well, first thing that comes to mind would be the collections. They are fairly complex in Clojure. How do you pass that back and forth between Clojure and Rust in a sane way? Meanwhile Chicken Scheme has straightforward ones, and since it just compiles to C anyway you basically get universally compatible arrays and C vectors which I'm sure Rust can handle out of the box. At the cost of not having immutability of course. For Clojure on the other hand, you'd have to develop an entire companion library.
Clojure collections are anything but complex
Not to you as a user of the language, but the implementation of them. With the shared structure among multiple copies with a shared ancestor, and all that stuff going on
it won't be zero copy, for sure
It just seems kinda silly to shoehorn a language that isn't designed with that in mind into the role of being an embedded language, is all
@zilti I can see what you mean yes. When I started thinking about exposing Clojure stuff to Rust, I basically already gave up on the idea 😉
btw, bodil implemented the clojure persistent data structures for rust as a rust lib 🙂
just as an aside
I wonder though if at some point there will be a higher common ground among programming languages. C types seem to still be the smallest common denominator
Oh, interesting. I know barely anything about Rust. But I've also seen a few libraries for Chicken Scheme that implement Clojure features like atoms
I also don't know Rust, basically reading through the book this weekend, I just saw this on Twitter a while ago