danielpclark / rutie

“The Tie Between Ruby and Rust.”
MIT License
942 stars 62 forks source link

Add `rb_proc_new` for creating Ruby procs in Rust #64

Open danielpclark opened 5 years ago

danielpclark commented 5 years ago

The Ruby C method rb_proc_new was created to “make Proc from C function”. This means we can also make a Proc from a Rust function.

The method signature is as follows in C:

VALUE
rb_proc_new(VALUE (*func)(ANYARGS) /* VALUE yieldarg[, VALUE procarg] */, VALUE val)
{ /* ... */ }

Which means the Rust representation may be one of the following:

pub fn rb_proc_new(func: CallbackPtr, val: Value) -> Value;
pub fn rb_proc_new(func: extern fn(Value, Option<Value>) -> Value, val: Value) -> Value;

I would like someone who has a more intimate knowledge of using FFI callback pointers in Rust to help create this and allow us to use Rust closures as Ruby procs.

danielpclark commented 5 years ago

@dsander How did you get such useful debug info? Looking at your issue I see what looks like lldb. Is that the tool you mainly used and did you have to run the code with Ruby calling Rust for it to be useful? I've tried to implement this proc feature several times now but the Rust output for a panic across the FFI boundary pretty much sums up to everything saying either thread or panic.

dsander commented 5 years ago

Yes I used lldb as it's, as far as I know, the only debugger available on MacOS. You can do both, attach it to a rust binary or a ruby process. To have debug information available you need at least debug = true enabled for the release build.

If your Rust/Ruby process segfaults you only need to run it with lldb:

Rust:

$ rust-lldb <path to the binary>
....
(lldb) run

Ruby

$ lldb
(lldb) target create ~/.rbenv/versions/2.5.3/bin/ruby
(lldb) run -Ilib your-ruby-script.rb

You can navigate through the stack using the up and down commands.

When I want to set breakpoints I am using the CodeLLDB extension for VSCode with this launch config:

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "lldb",
            "request": "launch",
            "name": "Debug",
            "program": "~/.rbenv/versions/2.5.3/bin/ruby",
            "args": ["-Ilib", "run.rb"],
            "cwd": "/working/directory"
        }
    ]
}