-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Investigate how to increase compatibility with ocaml-rs to ease integration #13
Comments
@zshipko this is not complete (in particular, I have to go through ocaml-derive to get a better idea of what should change), but if you have any comment, suggestion, question, or whatever just leave a comment here. |
Thanks, this looks good! I will go over it a few times and add a comment if anything else comes to mind, but it looks pretty complete already. Working on the |
@tizoc After spending a little time thinking about how to re-implement #[ocaml::func]
#[ocaml::roots(a)]
pub fn my_function(x: i32) -> i32 {
a_variable = x.to_ocaml(gc);
a_variable
} Another consideration is how we should allow #[ocaml::func(gc)] I can start an initial implementation in the next few weeks - I'm sure I'll run into some more cases like this where the ergonomics are a little different between the two libraries. |
Hi @zshipko! I haven't been active on this during the last week because I got sidetracked and been working on something else, but I plan to get back to this next week. One thing that is very likely to change, is that the It will work similarly to how the Any function that wants to perform an allocation or interact with the OCaml runtime will have to accept this as a parameter. The idea is for this handle to be the source of lifetimes for unrooted OCaml values (like the What needs to figured out is how to make this accessible to callback functions that are called from OCaml. My idea for now is to just have an unsafe (undocumented) function to get ahold of this runtime handle+lock, and then Whatever you come up in terms of API regarding the |
Thanks for the heads up, in that case I will take the opportunity to experiment with the interface a bit and see what works while those updates are in progress. |
@zshipko I'm thinking that I'm also thinking that there may be situations where declaring the name of the variable that will hold the OCaml runtime handle could be skipped too, making the Rust function automatically release the OCaml runtime lock to be able to run in parallel to the OCaml runtime. Anyway, this aspect will be clearer once I'm done with the aqcuire/release API. |
@tizoc I have been looking at this a little closer and am wondering what more needs to be done by the derive macros other than wrapping the functions in For instance, this: ocaml_export! {
fn twice_boxed_int(gc, num: OCaml<OCamlInt64>) -> OCaml<OCamlInt64> {
let num = num.to_rust();
let result = num * 2;
to_ocaml!(gc, result)
}
} would just become: #[derive(ocaml::func(gc))]
pub fn twice_boxed_int(num: OCaml<OCamlInt64>) -> OCaml<OCamlInt64> {
let num = num.to_rust();
let result = num * 2;
to_ocaml!(gc, result)
} Due to the introduction of |
@zshipko that is a valid implementation, yes. But eventually, I would like to get rid of that macro because the code is horrible. Note also that Maybe it is easier initially to just update the macros to handle that stuff, just to get the exported functions out of the way for now. If that is the case, then we can do that as a temporary solution. Btw, somewhat related to this: we have been discussing with the INRIA guys that in Rust, using a caller-save convention to function arguments (so that the exported function receives This is something I am playing with now in ocaml-interop. |
Cool, that sounds interesting! I have an implementation I'm happy with in https://github.com/zshipko/ocaml-rs/tree/interop2 - Just got tests working, but there still could be some other things I need to clean up. The There now an implicit |
Great. I expect to finish the new caller-saved args version of |
Just as a heads-up, I've been working on my own on adding missing features within ocaml-interop. The most polished branches are for bigarrays and passing Rust types to OCaml through custom blocks (will send PRs). I've also looked into catching panics, I've noticed that the current approach in ocaml-rs is to replace the hook that's used to print backtraces and call the OCaml runtime to throw, which I think should be changed to a catch_unwind-based approach. Directly calling caml_raise_with_arg which will unwind across the FFI boundary gets into UB territory. |
I have worked as much as I can on this pre-rooting changes, and will have a look at porting to these changes after that. |
I'm sending PRs for trivial stuff, and I'll hold on the rest (though, the branches are published) until you tell me it's fine to base work on your changes. |
@g2p sounds good. I'm revising some stuff, and changing a few names. I will let you know once it is ready. |
Merged some changes I have been working on since last month earlier today and released a new version. The main thing that changed is that function calls now center around A new caller-rooting calling convention is used, in contrast to the old (and OCaml's C API) callee-rooting convention (that is, on ocaml-interop, now it is the responsibility of the caller to root the values, while before it was up to the callee). This simplified some things, and there is no longer any need for using macros to call OCaml functions. Return values are still |
Nice! I have that PR open on ocaml-rs that uses ocaml-interop under the hood (zshipko/ocaml-rs#48). I'm still doing some testing and verification but it's looking good and I hope to be able to make a new release sometime in the next few weeks. I will make sure to tag you in that before I move forward though. |
WIP
Motivation
ocaml-rs already solves a bunch of things that are planned in
ocaml-interop
, andocaml-interop
already provides a safe API that could benefitocaml-rs
. The idea her is to figure out what would be necessary for "sandwiching"ocaml-interop
in-betweenocaml-sys
andocaml-rs
's higher level APIs.What
ocaml-interop
solves forocaml-rs
ocaml-rs
represents OCaml values asValue
,ocaml-interop
usesOCaml<T>
.ocaml-rs
has a 1-on-1 mapping between Rust and OCaml values, inocaml-interop
there is more flexibility and control on what can convert into what).What
ocaml-rs
solves forocaml-interop
ocaml-interop
uses macros to define how to map between Rust structs/enums and OCaml records/variants)Err
results to produce OCaml exceptionsocaml-interop
uses a wrapper macro for this)Ideas for the future
ocaml-rs
derivers, and combined withocaml-interop
's representation of OCaml values, implementations for interacting with OCaml records/variants could be generated forderive
annotated structs so that allocations that result from OCaml->Rust conversions can be avoided, or controlled with more granularity.Modifications Summary
Additions
WIP
ocaml-sys
: a macro likeocaml_frame
fromocaml-interop
but for plainValue
s to replacecaml_param
?Changes
WIP
ocaml-rs
:Value
would become a re-export ofocaml-interop
sOCaml<'a, T>
.ocaml-rs
: Exported functions would have an implicitocaml_frame
instead of ancaml_body
.Deprecations / Removals
WIP
ocaml-sys
:caml_param
andcaml_body
macros.ocaml_frame
macro fromocaml-interop
should be used instead (maybe a lower-level version that works usingRawOCaml
values could be implemented and added toocaml-sys
).ocaml-rs
:List
,Array
, etc types get replaced byOCaml<OCamlList<T>>
, etc types fromocaml-interop
.ocaml-interop
: most (all?) macros related to mapping between Rust<->OCaml Structs/Enums/RecordsVariants. Not needed when theocaml-rs
derivers exist (doesn't cover all the cases that the macros cover, but those are probably better handled by intermediary conversions anyway).ocaml-interop
:ocaml_export
macro, not needed when the function annotations fromocaml-rs
exist.Other
ocaml-rs
does a good job already, but it core OCaml could help us here, that would be great, because the OCaml runtime seems to be going through a bunch of changes lately).ocaml-interop
(norocaml-rs
?) for accessing the OCaml runtime, and is left for the user to handle. Having a solution baked into the libraries would be good.The text was updated successfully, but these errors were encountered: