Skip to content
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

Proposal: attribute to generate pre-encoded NIF functions #254

Closed
scrogson opened this issue Oct 17, 2019 · 9 comments
Closed

Proposal: attribute to generate pre-encoded NIF functions #254

scrogson opened this issue Oct 17, 2019 · 9 comments
Assignees

Comments

@scrogson
Copy link
Member

I'd like to see how far we can go to provide the most ergonomic API for building NIFs.

Given that all NIFs have the same signature:

static ERL_NIF_TERM fun(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])

It would be nice to provide a way to define a Rust function that would only be concerned with Rust types:

#[rustler::nif]
fn add(a: i64, b: i64) -> i64 {
  a + b
}

rustler::init!("Elixir.Math", [add]);

The arguments (a and b in this case) would automatically be decoded from
ERL_NIF_TERM to an i64. The return type (i64) would automatically be
encoded into the appropriate ERL_NIF_TERM.

Essentially, arguments must implement Decoder while all return types must implement Encoder.

I've started working on a PoC a while back (https://github.com/scrogson/rusterlium) and I'd like to see what others think about making this a reality.

Thoughts?

@evnu
Copy link
Member

evnu commented Oct 17, 2019

I like this format very much. Do you already have a plan how to handle extra options for exported nifs, such as SchedulerFlags?

@filmor
Copy link
Member

filmor commented Oct 17, 2019

I think it would still make sense to at least optionally allow Term arguments as well as passing the env in.

@filmor
Copy link
Member

filmor commented Oct 17, 2019

It would also be nice if this made listing the nifs optional in rustler::init!.

@scrogson
Copy link
Member Author

scrogson commented Oct 17, 2019

Do you already have a plan how to handle extra options for exported nifs, such as SchedulerFlags?

Yes. It would be handled in the attribute:

#[rustler::nif(name = "add2", schedule = "DirtyCpu"]
fn add(a: i64, b: i64) -> i64 {
    a + b
}

I think it would still make sense to at least optionally allow Term arguments as well as passing the env in.

I definitely agree that Env will need to be supported. I'm struggling with a scenario where Term would be needed though.

It would also be nice if this made listing the nifs optional in rustler::init!.

Yeah, it would be, but I don't think there is a way around that. We need a way to map the function pointer to the wrapped implementation.

This seems similar to how Rocket's routing works as well.

@scrogson scrogson self-assigned this Oct 18, 2019
@scrogson
Copy link
Member Author

I'm starting work on this. I hope to have a PR ready soon-ish.

@hansihe
Copy link
Member

hansihe commented Oct 18, 2019

Really like this!

I think it would still make sense to at least optionally allow Term arguments as well as passing the env in.

We get that basically for free, since both Decoder<Term> and Encoder<Term> is implemented for Term.

@filmor
Copy link
Member

filmor commented Oct 18, 2019

@sunny-g Do you see a good way of adjusting your PR (#232) to this?

I think it would still make sense to at least optionally allow Term arguments as well as passing the env in.

I definitely agree that Env will need to be supported. I'm struggling with a scenario where Term would be needed though.

Depends on how much "parameter interpretation" you want to implement in Erlang/Elixir.

It would also be nice if this made listing the nifs optional in rustler::init!.

Yeah, it would be, but I don't think there is a way around that. We need a way to map the function pointer to the wrapped implementation.

Apart from changing how init! works entirely (wrapping all nifs in the macro call), we'll have to wait for rust-lang/rust#44034 to materialise, I guess.

@sunny-g
Copy link
Contributor

sunny-g commented Oct 19, 2019

@filmor Not immediately, as it'll likely depend on how this gets implemented.

At first glance, it might help if the rustler::nif attribute also generated the function's associated unsafe extern "C" fn(NIF_ENV, i32, *const NIF_TERM) -> NIF_TERM, or the function's ErlNifFunc , inline with it so that it'd be in-scope for a similar macro to what I implemented already.

@sunny-g
Copy link
Contributor

sunny-g commented May 26, 2021

@filmor updated my schedule_nif PR to support the new NIF macros here: #232

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants