Taaitaaiger / jlrs

Julia bindings for Rust
MIT License
408 stars 21 forks source link

Can't do file IO in the Julia process #135

Closed drsk0 closed 3 weeks ago

drsk0 commented 3 weeks ago

Opening and reading a file with the given Julia sysimage doesn't work. I'm trying to read a JLD2 file in the Julia process to parse parameters for a ML model, but I get a warning

Warning: Opening file with JLD2.MmapIO failed, falling back to IOStream

after which the process dies. Opening any other file also fails. I'm not sure if this is intended or a bug. If it's intended, how should I get the parameters to my model from the Rust process?

Taaitaaiger commented 3 weeks ago

What version of jlrs and Julia are you using, and could you share some code that fails?

drsk0 commented 3 weeks ago

I'm using jlrs 19.2 and Julia 1.10.2. Here's the simplified Julia code:

function run(args::RunArgs)
    @unpack dims, fixed_dims, n, threshold = args
    @info "opening file"
    tmp = open("test.txt")
    @info read(tmp, String)
    ts = JLD2.load_object("./latest_ts.jld2")
    @info "found ts file"
    for xs in ch_samples
        @info "new sample"
        @info xs
    end
end

And here's the simplified code on the Rust side:

#[repr(C)]
#[derive(
    Clone, Debug, Unbox, ValidLayout, Typecheck, ValidField, ConstructType, CCallArg, IntoJulia,
)]
#[jlrs(julia_type = "Main.RunArgs")]
pub struct RunArgs {
    pub dims: i64,
    pub fixed_dims: i64,
    pub n: i64,
    pub threshold: f32,
}

struct RunTask {
    args: RunArgs,
}

#[async_trait(?Send)]
impl AsyncTask for RunTask {
    type Output = usize;
    type Affinity = DispatchAny;

    async fn run<'frame>(&mut self, mut frame: AsyncGcFrame<'frame>) -> JlrsResult<Self::Output> {
        let args = Value::new(&mut frame, self.args.clone());

        let func = Module::main(&frame).function(&mut frame, "run")?;

        // CallAsync::call_async schedules the function call on another
        // thread and returns a Future that resolves when the scheduled
        // function has returned or thrown an error.
        unsafe { func.call_async(&mut frame, [args]) }
            .await
            .into_jlrs_result()?
            .unbox::<usize>()
    }
}
Taaitaaiger commented 3 weeks ago

Thanks! I'll take a look this weekend.

drsk0 commented 3 weeks ago

Thanks a lot, highly appreciated!

drsk0 commented 3 weeks ago

Hey, I just figured this out. It simply didn't find the file. I assumed the Julia process was running in the project directory of the Julia source code, alas the correct current working directory is the one of the Rust process. Now everything works as expected! Thanks a lot anyway, the Jlrs library is super nice to work with!

Taaitaaiger commented 3 weeks ago

Glad to hear you fixed it! Feel free to open an issue if you run into anything else.

Quick word of warning: jlrs 0.20 has recently been released and makes some significant backwards incompatible changes w.r.t. the async runtime.