Giter Site home page Giter Site logo

rusterlium / rustler Goto Github PK

View Code? Open in Web Editor NEW
4.1K 79.0 215.0 2.02 MB

Safe Rust bridge for creating Erlang NIF functions

Home Page: https://docs.rs/crate/rustler

License: Apache License 2.0

Rust 78.45% Elixir 20.13% Erlang 0.03% HTML 0.06% Shell 1.21% C 0.13%
erlang nif elixir ffi binding rust

rustler's People

Contributors

alex-shapiro avatar ayrat555 avatar bcksl avatar cleaton avatar cocoa-xu avatar cristianberneanu avatar davydog187 avatar dependabot-preview[bot] avatar dovahcrow avatar dvic avatar evnu avatar filmor avatar goertzenator avatar hansihe avatar ishitatsuyuki avatar jaykickliter avatar jorendorff avatar josevalim avatar kaaboaye avatar kianmeng avatar madninja avatar philss avatar qqwy avatar scrogson avatar seokminhong avatar tatsuya6502 avatar thiamsantos avatar thomas9911 avatar virviil avatar yjh0502 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rustler's Issues

support for erlang's dirty scheduler?

Since rust in erlang is often used to do cpu intensive job, should rustler supports dirty scheduler? Otherwise rust calls will block erlang VM too long.

Make sure all relevant erl_nif functionality is represented in some way

If there is anything in particular you need, please comment below and we can work something out.

Primitives

Primitives are fully supported through Encoder.

  • enif_get_double()
  • enif_get_int()
  • enif_get_int64()
  • enif_get_long()
  • enif_get_uint()
  • enif_get_uint64()
  • enif_get_ulong()
  • enif_make_double()
  • enif_make_int64()
  • enif_make_long()
  • enif_make_int()
  • enif_make_uint()
  • enif_make_uint64()
  • enif_make_ulong()

Atoms

  • enif_get_atom()
  • enif_get_atom_length() Will add if anyone has a legitimate use.
  • enif_make_existing_atom() N/A
  • enif_make_existing_atom_len()
  • enif_make_atom() N/A
  • enif_make_atom_len()

Lists

  • enif_make_reverse_list() NifTerm::list_reverse()
  • enif_get_list_cell() NifTerm::list_get_cell()
  • enif_get_list_length() NifTerm::list_length()
  • enif_make_list()
  • enif_make_list_from_array()
  • enif_make_list_cell()
  • enif_make_string_len()

Char lists

  • enif_make_string()
  • enif_get_string()

Maps

  • enif_get_map_size()
  • enif_get_map_value()
  • enif_make_map_put()
  • enif_make_map_remove()
  • enif_make_map_update()
  • enif_map_iterator_create()
  • enif_map_iterator_get_pair()
  • enif_map_iterator_is_head()
  • enif_map_iterator_is_tail()
  • enif_map_iterator_next()
  • enif_map_iterator_prev()
  • enif_map_iterator_destroy()
  • enif_make_new_map()

Binaries

Supported through binary abstraction.

  • enif_alloc_binary()
  • enif_realloc_binary()
  • enif_inspect_binary()
  • enif_inspect_iolist_as_binary()
  • enif_make_new_binary()
  • enif_release_binary()
  • enif_make_binary()
  • enif_make_sub_binary()

Tuples

  • enif_get_tuple()
  • enif_make_tuple_from_array()
  • enif_make_tuple() N/A

Resources

Exposed through resource abstraction.

  • enif_keep_resource()
  • enif_get_resource()
  • enif_sizeof_resource()
  • enif_release_resource()
  • enif_alloc_resource()
  • enif_make_resource()
  • enif_open_resource_type()
  • enif_make_resource_binary()

Misc terms

  • enif_make_pid()
  • enif_make_ref()
  • enif_get_local_pid()
  • enif_get_local_port()

Term utils

  • enif_make_copy()
  • enif_term_to_binary()
  • enif_binary_to_term()
  • enif_compare()
  • enif_is_identical()
  • enif_snprintf()
  • enif_port_command()
  • enif_is_port_alive()
  • enif_is_process_alive()

Type tests

Exposed as methods on NifTerm.

  • enif_is_atom()
  • enif_is_binary()
  • enif_is_list()
  • enif_is_pid()
  • enif_is_port()
  • enif_is_ref()
  • enif_is_tuple()
  • enif_is_empty_list()
  • enif_is_exception()
  • enif_is_fun()
  • enif_is_map()
  • enif_is_number()

Scheduling

  • enif_consume_timeslice()
  • enif_schedule_nif() See this

Exceptions

  • enif_has_pending_exception() Useless for us since we don't expose raise_exception to the user.

Supported through rustler::Error. It is undesirable to expose these directly:

  • enif_make_badarg()
  • enif_raise_exception()

Env

  • enif_free_env()
  • enif_clear_env()
  • enif_alloc_env()
  • enif_self()
  • enif_send() See this

Time

  • enif_cpu_time()
  • enif_now_time()
  • enif_monotonic_time()
  • enif_time_offset()
  • enif_convert_time_unit()

Misc

  • enif_getenv()
  • enif_alloc() N/A
  • enif_free() N/A
  • enif_priv_data() No plans to support.
  • enif_system_info()
  • enif_make_unique_integer()
  • enif_is_current_process_alive()

Threading

Rust has its own threading APIs. There are no plans to support this.

  • enif_rwlock_tryrlock()
  • enif_rwlock_tryrwlock()
  • enif_thread_create()
  • enif_thread_join()
  • enif_tsd_key_create()
  • enif_mutex_trylock()
  • enif_thread_type()
  • enif_equal_tids()
  • enif_cond_broadcast()
  • enif_cond_destroy()
  • enif_cond_signal()
  • enif_cond_wait()
  • enif_mutex_destroy()
  • enif_mutex_lock()
  • enif_mutex_unlock()
  • enif_rwlock_destroy()
  • enif_rwlock_rlock()
  • enif_rwlock_runlock()
  • enif_rwlock_rwlock()
  • enif_rwlock_rwunlock()
  • enif_thread_exit()
  • enif_thread_opts_destroy()
  • enif_tsd_key_destroy()
  • enif_tsd_set()
  • enif_tsd_get()
  • enif_cond_create()
  • enif_mutex_create()
  • enif_rwlock_create()
  • enif_thread_opts_create()
  • enif_thread_self()

New API for using atoms

Goals

  • eliminate the string lookup every time you want to use an atom
  • make it easier to remember how to use atoms :)

Maybe users should write this:

declare_atoms!(ATOMS, [ok, error, ponies]);

and then, whenever they need an atom, simply ATOMS.ok() or ATOMS.ponies().to_term(env) or whatever.

Kind of unfortunate that the .to_term(env) is still necessary :-\

Improve usability

@jorendorff recently wrote a test project with rustler, and provided some usability feedback. We should see what we can do to remedy these issues.

  1. It felt like too much manual configuration setup was needed.
  2. Error handling was a pain.
  3. Converting argument types, surprisingly, was a pain. str implements NifEncoder, but String and &str do not. This means you can't call .encode() on a tuple containing a string!
  4. I tried making a resource for a type provided by the image crate and got a coherence error. Had to define a newtype. I don't know if there's anything we can do about that.
  5. It seems like the type of args should be &[NifTerm], not &Vec<NifTerm>.

Let me try to address this in order.

  1. I definitely agree that getting up and running is way too hard at the moment. We should look at what we can do to improve the boilerplate generator, and we should try to write some guides.
  2. I have felt bad about how error handling works for a while now. I am unsure what the best way to improve this would be, and feedback is definitely welcome in #2.
  3. If there is no better way of doing it, we should write those additional implementations. Doing this feels like a workaround, but I am not sure if there is a better way of doing it.
  4. I am aware of this, and have experienced it myself, but I am not sure if there is anything we can do to fix this.
  5. Agreed. I seem to remember it was &[NifTerm] originally, and I am unsure when this was changed.

If there are anyone else having problems with usability, please post it in the comments. I would very much like to know where the pain-points are, so that we can look at addressing them.

Correct version of rust is not accepted when using rustup

This is the ouput of a fresh mix project, where just the things from the documentation have been added.

$ mix compile
warning: 'multirust' is being renamed to 'rustup'. this command is deprecated. use 'rustup' instead
Required Rust toolchain version nightly-2016-05-07 is not installed.
It can be installed by running 'multirust update nightly-2016-05-07'.

** (RuntimeError) Compilation error
    lib/compiler.ex:9: Mix.Tasks.Compile.Rustler.throw_error/1
    lib/compiler.ex:22: Mix.Tasks.Compile.Rustler.run/1
    (elixir) lib/enum.ex:1105: Enum."-map/2-lists^map/1-0-"/2
    (mix) lib/mix/tasks/compile.all.ex:19: anonymous fn/1 in Mix.Tasks.Compile.All.run/1
    (mix) lib/mix/tasks/compile.all.ex:37: Mix.Tasks.Compile.All.with_logger_app/1
    (mix) lib/mix/tasks/compile.ex:84: Mix.Tasks.Compile.run/1
    (mix) lib/mix/cli.ex:58: Mix.CLI.run_task/2

$ rustup show
installed toolchains
--------------------

nightly-2016-05-07-x86_64-unknown-linux-gnu
nightly-x86_64-unknown-linux-gnu (default)

active toolchain
----------------

nightly-2016-05-07-x86_64-unknown-linux-gnu (directory override for '/home/NobbZ/projects/elixir/rustler_foo')
rustc 1.10.0-nightly (62e2b2fb7 2016-05-06)


$ rustc --version
rustc 1.10.0-nightly (62e2b2fb7 2016-05-06)

Unable to cargo build rustler

Hi,
Rustler seems to be very promising but unfortunately I am not able to compile it.

OS: Mac OS X siera
Rust Version: 1.12.0.

The error I am getting is:

$ cargo build
    Updating registry `https://github.com/rust-lang/crates.io-index`
   Compiling easy-plugin-plugins v0.9.1
error: no method named `pat_enum` found for type `&mut syntax::ext::base::ExtCtxt<'_>` in the current scope
   --> /Users/tomaskorcak/dev/microcrawler/gauc-elixir/native/gauc/target/debug/build/easy-plugin-plugins-64578d19b8e93d12/out/lib.rs:624:23
    |
624 |     let pat = context.pat_enum(span, path, pats);
    |                       ^^^^^^^^
/Users/tomaskorcak/.cargo/registry/src/github.com-1ecc6299db9ec823/easy-plugin-plugins-0.9.1/src/lib.rs:36:1: 36:47 note: in this expansion of include!

error: aborting due to previous error

error: Could not compile `easy-plugin-plugins`.

To learn more, run the command again with --verbose.

Should NifTerm be an enum?

It would be really nice to be able to use match on any NifTerm.

pub enum NifTerm<'a> {
    Atom { term: NIF_TERM, env: &'a NifEnv },
    Binary { term: NIF_TERM, env: &'a NifEnv },
    EmptyList { term: NIF_TERM, env: &'a NifEnv },
    Exception { term: NIF_TERM, env: &'a NifEnv },
    Fun { term: NIF_TERM, env: &'a NifEnv },
    List { term: NIF_TERM, env: &'a NifEnv },
    Map { term: NIF_TERM, env: &'a NifEnv },
    Pid { term: NIF_TERM, env: &'a NifEnv },
    Port { term: NIF_TERM, env: &'a NifEnv },
    Ref { term: NIF_TERM, env: &'a NifEnv },
    Tuple { term: NIF_TERM, env: &'a NifEnv },
}

There are enif_is_* functions available in the erlang_nif_sys to determine each of the variants above.

@hansihe thoughts?

compiling rustler-0.13.0 failed

error[E0308]: mismatched types
--> /home/chengwei/.cargo/registry/src/github.com-1ecc6299db9ec823/rustler-0.13.0/src/wrapper/nif_interface.rs:178:68
|
178 | erlang_nif_sys::enif_open_resource_type(env, module_str, name, dtor, flags, tried)
| ^^^^ expected unsafe fn, found normal fn
|
= note: expected type std::option::Option<unsafe extern "C" fn(*mut wrapper::nif_interface::erlang_nif_sys::ErlNifEnv, *mut std::os::raw::c_void)>
= note: found type std::option::Option<extern "C" fn(*mut wrapper::nif_interface::erlang_nif_sys::ErlNifEnv, *mut std::os::raw::c_void)>

error[E0308]: mismatched types
--> /home/chengwei/.cargo/registry/src/github.com-1ecc6299db9ec823/rustler-0.13.0/src/wrapper/nif_interface.rs:226:61
|
226 | erlang_nif_sys::enif_schedule_nif(env, fun_name, flags, dtor, argc, argv)
| ^^^^ expected unsafe fn, found normal fn
|
= note: expected type std::option::Option<unsafe extern "C" fn(*mut wrapper::nif_interface::erlang_nif_sys::ErlNifEnv, i32, *const usize)>
= note: found type std::option::Option<extern "C" fn(*mut wrapper::nif_interface::erlang_nif_sys::ErlNifEnv, i32, *const usize)>

error: aborting due to 2 previous errors

Testing NIFs

What is the recommended way to test NIFs in rustler?

Does one implement tests in elixir that test the wrapping module? Does one write tests in rust? If the latter, how are they run?

Improvements to NifTerm

Right now the lifetime of NifTerm is limited through a PhantomData reference to a NifEnv. While this guarantees that the term is not used outside of its life, it does not guarantee that is it used with the same NifEnv that created it. This is not a problem at the moment, as a Nif only really can get a reference to the NifEnv that called it. In the future this might pose an issue, as we might want to expose the functionality of owned nif environments.

List of things that are done badly at the moment and that might break when we expose owned environments:

  • NifTerm -> NifTerm NifEncoder in terms.rs

Leading slash in relative path

In the documentation there is written:

  • path - The path to the crate directory relative to the project root.

But when do use something that looks like a relative path (eg. native/foo), compiliation fails with a message like the following:

Compiling NIF crate :foo (native/foo)...
Directory '/home/nobbz/projects/elixir/projectnative/foo' could not be found.
One of the crate directories specified for compilation does not exist.

If I do prepend that with a slash, then compilation works, but /native/foo looks like an absolute path.

Generated stubs create type-mismatch

After I was able to circumvent other problems, already reported here (#66, #67) I do now get the errors below. I have not touched the generated stubs.

Compiling NIF crate :spacecolony_nif (native/spacecolony_nif)...
   Compiling spacecolony_nif v0.1.0 (file:///home/nobbz/projects/elixir/space_colony/native/spacecolony_nif)
error[E0308]: mismatched types
 --> /home/nobbz/projects/elixir/space_colony/_build/dev/rustler_crates/spacecolony_nif/debug/build/spacecolony_nif-ecbe9ff9de559671/out/lib.rs:9:29
  |
9 |     Ok((num1 + num2).encode(env))
  |                             ^^^ expected struct `rustler::NifEnv`, found reference
  |
  = note: expected type `rustler::NifEnv<'_>`
  = note:    found type `&'a rustler::NifEnv<'_>`

error[E0308]: mismatched types
  --> src/lib.rs:15:1
   |
15 | include!(concat!(env!("OUT_DIR"), "/lib.rs"));
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `rustler::NifEnv`, found reference
   |
   = note: expected type `fn(rustler::NifEnv<'a>, &std::vec::Vec<rustler::NifTerm<'a>>) -> std::result::Result<rustler::NifTerm<'a>, rustler::NifError>`
   = note:    found type `fn(&'a rustler::NifEnv<'_>, &std::vec::Vec<rustler::NifTerm<'_>>) -> std::result::Result<rustler::NifTerm<'a>, rustler::NifError> {add}`
   = note: this error originates in a macro outside of the current crate

error: aborting due to 2 previous errors

Follow `enif_send` contract.

As @hansihe notes in #44 (comment)

The first argument to enif_send is "The environment of the calling process. Must be NULL only if calling from a created thread." Instead, we pass an OwnedEnv, which isn't associated with any process.

It "seems to work for now" but obviously we should code to the spec.

Tiny memory leak in `rustler_export_nifs`

                name: ::std::ffi::CString::new($name).unwrap().into_raw() as *const u8,

I don't think this is safe; I think the CString is freed at the end of the statement.

Maybe we can do this instead:

    name: concat!($name, "\x00").as_bytes() as *const u8,

Taking a look at html5ever parsing

I did a google and your name came up! Did you ever have a quick stab at this? I have a feeling it would be very useful and much better than :mochiweb. With Rustler it should also be quite safe too.

The structure that Floki uses for parsed html looks about what we want out of html5ever and fairly simple...

Fix names in src/resource.rs

Right now the naming of the different things related to resources is less than ideal. Several of the structs used have confusing names.

Fix build issues on Mac

Not sure if this is a OS X-specific issue:

Cargo.toml

[package]
name = "rustler_test"
version = "0.1.0"
authors = []

[lib]
name = "rustler_test"
path = "src/nif.rs"
crate_type = ["dylib"]

[dependencies]
rustler = "0.8.1"
rustler_codegen = "0.8.1"

src/nif.rs

#![feature(plugin)]
#![plugin(rustler_codegen)]

#[macro_use]
extern crate rustler;
use rustler::{ NifEnv, NifTerm, NifResult, NifEncoder };

rustler_export_nifs!(
    "Elixir.RustlerTest",
    [("add", 2, add)],
    None
);

fn add<'a>(env: &'a NifEnv, args: &Vec<NifTerm>) -> NifResult<NifTerm<'a>> {
    let num1: i64 = try!(args[0].decode());
    let num2: i64 = try!(args[1].decode());
    Ok((num1 + num2).encode(env))
}
$ multirust run nightly-2016-04-05 mix rustler.check
Rustler environment verified
$ multirust run nightly-2016-04-05 cargo build
   Compiling lazy_static v0.1.16
   Compiling easy-plugin v0.3.0
   Compiling aster v0.14.0
   Compiling libc v0.2.10
   Compiling ruster_unsafe v0.4.0
   Compiling rustler v0.8.1
   Compiling rustler_codegen v0.8.1
   Compiling rustler_test v0.1.0 (file:///Users/brendan/code/dev-day/elixir_rustler_test)
error: linking with `cc` failed: exit code: 1
note: "cc" "-m64" "-L" "/Users/brendan/.multirust/toolchains/nightly-2016-04-05/lib/rustlib/x86_64-apple-darwin/lib" "/Users/brendan/code/dev-day/elixir_rustler_test/target/debug/rustler_test.0.o" "-o" "/Users/brendan/code/dev-day/elixir_rustler_test/target/debug/librustler_test.dylib" "/Users/brendan/code/dev-day/elixir_rustler_test/target/debug/rustler_test.metadata.o" "-Wl,-dead_strip" "-nodefaultlibs" "-L" "/Users/brendan/code/dev-day/elixir_rustler_test/target/debug" "-L" "/Users/brendan/code/dev-day/elixir_rustler_test/target/debug/deps" "-L" "/Users/brendan/.multirust/toolchains/nightly-2016-04-05/lib/rustlib/x86_64-apple-darwin/lib" "-Wl,-force_load,/var/folders/z3/g4m3xbnj11q6m76kzg8w683c0000gn/T/rustc.QBlM3AicSUqg/librustler-12f16f7939d96e54.rlib" "-Wl,-force_load,/var/folders/z3/g4m3xbnj11q6m76kzg8w683c0000gn/T/rustc.QBlM3AicSUqg/libruster_unsafe-badf32d60ecc0604.rlib" "-Wl,-force_load,/var/folders/z3/g4m3xbnj11q6m76kzg8w683c0000gn/T/rustc.QBlM3AicSUqg/liblibc-30c6b6751f89189b.rlib" "-Wl,-force_load,/var/folders/z3/g4m3xbnj11q6m76kzg8w683c0000gn/T/rustc.QBlM3AicSUqg/liblazy_static-5e6d9f365bf63baa.rlib" "-Wl,-force_load,/var/folders/z3/g4m3xbnj11q6m76kzg8w683c0000gn/T/rustc.QBlM3AicSUqg/libstd-18402db3.rlib" "-Wl,-force_load,/var/folders/z3/g4m3xbnj11q6m76kzg8w683c0000gn/T/rustc.QBlM3AicSUqg/libcollections-18402db3.rlib" "-Wl,-force_load,/var/folders/z3/g4m3xbnj11q6m76kzg8w683c0000gn/T/rustc.QBlM3AicSUqg/librustc_unicode-18402db3.rlib" "-Wl,-force_load,/var/folders/z3/g4m3xbnj11q6m76kzg8w683c0000gn/T/rustc.QBlM3AicSUqg/librand-18402db3.rlib" "-Wl,-force_load,/var/folders/z3/g4m3xbnj11q6m76kzg8w683c0000gn/T/rustc.QBlM3AicSUqg/liballoc-18402db3.rlib" "-Wl,-force_load,/var/folders/z3/g4m3xbnj11q6m76kzg8w683c0000gn/T/rustc.QBlM3AicSUqg/liballoc_system-18402db3.rlib" "-Wl,-force_load,/var/folders/z3/g4m3xbnj11q6m76kzg8w683c0000gn/T/rustc.QBlM3AicSUqg/liblibc-18402db3.rlib" "-Wl,-force_load,/var/folders/z3/g4m3xbnj11q6m76kzg8w683c0000gn/T/rustc.QBlM3AicSUqg/libcore-18402db3.rlib" "-l" "System" "-l" "pthread" "-l" "c" "-l" "m" "-dynamiclib" "-Wl,-dylib" "-l" "compiler-rt"
note: Undefined symbols for architecture x86_64:
  "_enif_make_double", referenced from:
      rustler::wrapper::nif_interface::enif_make_double::hd19548d32bb32295 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      _$LT$f64$u20$as$u20$types..NifEncoder$GT$::encode::h706149e7449ffee2 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      _$LT$f32$u20$as$u20$types..NifEncoder$GT$::encode::h144f24ce0170a8e0 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_get_ulong", referenced from:
      ruster_unsafe::enif_get_uint64::h64c3175e0dbcd390 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      ruster_unsafe::enif_get_uint64::h64c3175e0dbcd390 in libruster_unsafe-badf32d60ecc0604.rlib(ruster_unsafe-badf32d60ecc0604.0.o)
  "_enif_make_ulong", referenced from:
      ruster_unsafe::enif_make_uint64::h4fba0e724d8e25b6 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      ruster_unsafe::enif_make_uint64::h4fba0e724d8e25b6 in libruster_unsafe-badf32d60ecc0604.rlib(ruster_unsafe-badf32d60ecc0604.0.o)
  "_enif_make_long", referenced from:
      ruster_unsafe::enif_make_int64::hbc1979f2890ffe9c in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      ruster_unsafe::enif_make_int64::hbc1979f2890ffe9c in libruster_unsafe-badf32d60ecc0604.rlib(ruster_unsafe-badf32d60ecc0604.0.o)
  "_enif_get_uint", referenced from:
      rustler::wrapper::nif_interface::enif_get_uint::h5c5a16f0a01fde37 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      _$LT$u32$u20$as$u20$types..NifDecoder$LT$$u27$a$GT$$GT$::decode::haf5c58d5060cb07f in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      _$LT$u8$u20$as$u20$types..NifDecoder$LT$$u27$a$GT$$GT$::decode::h3e7e1bef75d03b42 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      _$LT$u16$u20$as$u20$types..NifDecoder$LT$$u27$a$GT$$GT$::decode::h1e7efa45cf0cba98 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_get_int", referenced from:
      rustler::wrapper::nif_interface::enif_get_int::hc379e848b0f1fa91 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      _$LT$i32$u20$as$u20$types..NifDecoder$LT$$u27$a$GT$$GT$::decode::h1c37e7be14e575ae in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      _$LT$i8$u20$as$u20$types..NifDecoder$LT$$u27$a$GT$$GT$::decode::ha035f42162eb16a1 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      _$LT$i16$u20$as$u20$types..NifDecoder$LT$$u27$a$GT$$GT$::decode::h5a81998157625a57 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_make_int", referenced from:
      rustler::wrapper::nif_interface::enif_make_int::h60d93b2ae4a8c8d3 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      _$LT$i32$u20$as$u20$types..NifEncoder$GT$::encode::h7ddd4380fe5dda18 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      _$LT$i8$u20$as$u20$types..NifEncoder$GT$::encode::hdc7675ac9b527c9f in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      _$LT$i16$u20$as$u20$types..NifEncoder$GT$::encode::hb0da2bfd44111ec8 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_keep_resource", referenced from:
      rustler::wrapper::nif_interface::enif_keep_resource::hcf8953a093156f6c in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_release_resource", referenced from:
      rustler::wrapper::nif_interface::enif_release_resource::hcddf0787bf6dbeeb in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_make_atom_len", referenced from:
      rustler::wrapper::nif_interface::enif_make_atom_len::he20a8a9702701fff in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_get_resource", referenced from:
      rustler::wrapper::nif_interface::enif_get_resource::h47d539fa331c39f3 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_make_resource", referenced from:
      rustler::wrapper::nif_interface::enif_make_resource::hb81c16919c920cad in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_alloc_resource", referenced from:
      rustler::wrapper::nif_interface::enif_alloc_resource::h68237ee990d1cf46 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_make_uint", referenced from:
      rustler::wrapper::nif_interface::enif_make_uint::hfe8668de47444792 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      _$LT$u32$u20$as$u20$types..NifEncoder$GT$::encode::h868c09d12496aeec in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      _$LT$u8$u20$as$u20$types..NifEncoder$GT$::encode::h11ad232d66e87a7d in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      _$LT$u16$u20$as$u20$types..NifEncoder$GT$::encode::h201a5388c8670d75 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_make_map_update", referenced from:
      rustler::wrapper::nif_interface::enif_make_map_update::hf5941f5f4b1d847b in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_get_map_value", referenced from:
      rustler::wrapper::nif_interface::enif_get_map_value::hc296d9a0bd30c233 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_make_map_put", referenced from:
      rustler::wrapper::nif_interface::enif_make_map_put::ha859d99862427ecd in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_open_resource_type", referenced from:
      rustler::wrapper::nif_interface::enif_open_resource_type::h12583a80f65f5745 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_make_new_map", referenced from:
      rustler::wrapper::nif_interface::enif_make_new_map::h907851f26b8541d0 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_make_badarg", referenced from:
      rustler::wrapper::nif_interface::enif_make_badarg::h4841a4ca720a65e5 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_get_tuple", referenced from:
      rustler::wrapper::nif_interface::enif_get_tuple::h7fd11d0d72fa7d45 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_get_long", referenced from:
      ruster_unsafe::enif_get_int64::hebc458f802f3215b in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      ruster_unsafe::enif_get_int64::hebc458f802f3215b in libruster_unsafe-badf32d60ecc0604.rlib(ruster_unsafe-badf32d60ecc0604.0.o)
  "_enif_get_map_size", referenced from:
      rustler::wrapper::nif_interface::enif_get_map_size::h3f9747fdd9d0f47c in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_make_tuple_from_array", referenced from:
      rustler::wrapper::nif_interface::enif_make_tuple_from_array::h7befd54d882d7531 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_make_map_remove", referenced from:
      rustler::wrapper::nif_interface::enif_make_map_remove::h961aa87e2152ef7f in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_is_atom", referenced from:
      rustler::wrapper::nif_interface::enif_is_atom::h334838d6a8353d15 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_make_copy", referenced from:
      rustler::wrapper::nif_interface::enif_make_copy::h810279a726029774 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_inspect_binary", referenced from:
      rustler::wrapper::nif_interface::enif_inspect_binary::h060c7c6692faf746 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      rustler::binary::NifBinary::from_term::h00da1e274a0cd422 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_alloc_env", referenced from:
      rustler::wrapper::nif_interface::enif_alloc_env::h3fd2c1de3d6068bc in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_make_binary", referenced from:
      rustler::wrapper::nif_interface::enif_make_binary::hdd6097cc32618309 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      rustler::binary::NifBinary::from_owned::h538759bc101b2b41 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_alloc_binary", referenced from:
      rustler::wrapper::nif_interface::enif_alloc_binary::h08bb424d3fa65f76 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      rustler::binary::OwnedNifBinary::alloc::hf56f1176ed8c3872 in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_release_binary", referenced from:
      rustler::wrapper::nif_interface::enif_release_binary::hcd3611ded3fa4e8e in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      _$LT$binary..OwnedNifBinary$u20$as$u20$std..ops..Drop$GT$::drop::hce6f374d6af3cdab in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_get_double", referenced from:
      rustler::wrapper::nif_interface::enif_get_double::h0954e2466735bdec in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      _$LT$f64$u20$as$u20$types..NifDecoder$LT$$u27$a$GT$$GT$::decode::h3c4a4cbd31f2a5df in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
      _$LT$f32$u20$as$u20$types..NifDecoder$LT$$u27$a$GT$$GT$::decode::h7abf1a0ce08162cb in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
  "_enif_raise_exception", referenced from:
      rustler::wrapper::nif_interface::enif_raise_exception::hfb9038fb735943ae in librustler-12f16f7939d96e54.rlib(rustler-12f16f7939d96e54.0.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

error: aborting due to previous error
error: Could not compile `rustler_test`.

To learn more, run the command again with --verbose.

Cross-compilation

Hi! I'm really glad to see this project!

I'm curious if there is a documented path for cross-compiling NIFs using rustler when used with releases. More specifically, if I have a cross-compiled ERTS from some other architecture, I can build a release for that architecture, but NIFs must also be cross-compiled for that to work. I would like to build NIFs using Rust, and I know it has facilities for cross-compilation, but reading through the documentation it wasn't clear how I would specify that in my configuration. To be clear, I'm very new to Rust, and I don't have immediate plans to write any NIFs, but as I'm the maintainer of distillery, one of the things I'd like to do this year is make building cross-compiled releases easier to set up.

If this is something that is already provided by the toolchain, perhaps some notes on how to configure it would be a good idea to add in the docs?

Move functionality out of the compiler plugin

While the elixir struct and tuple attribute are impossible to do with normal macros, the NIF function export may be doable.

If this turns out to be doable, it would be possible to run Rustler on Rust stable.

The next step after that would be to use something like syntex to get the elixir struct and tuple attribute on stable as well.

Tuple support?

Hello,

I'm trying to create a function in rust which takes two tuples, but it fails.

#[macro_use] extern crate rustler;
#[macro_use] extern crate rustler_codegen;
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate geo;

use rustler::{NifEnv, NifTuple, NifTerm, NifResult, NifEncoder};

#[derive(NifTuple)]
struct PointTuple {
    lat: f64,
    long: f64,
}

fn centroid<'a>(env: NifEnv<'a>, args: &[NifTerm<'a>]) -> NifResult<NifTerm<'a>> {

    // println!("{:&}", args);
    let p1: PointTuple = try!(args[0].decode());
    let p2: PointTuple = try!(args[1].decode());

   ...

Error message:

error: custom derive attribute panicked
  --> src/lib.rs:26:10
   |
26 | #[derive(NifTuple)]
   |          ^^^^^^^^
   |
   = help: message: assertion failed: !p.is_null()

If I also run mix test inside rustler/test I get the same error.

error: custom derive attribute panicked
 --> src/test_codegen.rs:4:10
  |
4 | #[derive(NifTuple)]
  |          ^^^^^^^^
  |
  = help: message: assertion failed: !p.is_null()

error: Could not compile `rustler_test`.

Its there a way to handle tuples as arguments in functions?
Thank you!

Unable to enable dirty scheduling

error: no rules expected the token `,`
  --> src/lib.rs:24:46
   |
24 |      ("decode_dirty", 2, decoder::naive_parse, ERL_NIF_DIRTY_JOB_CPU_BOUND),
   |                                              ^

Serde support

Working with these can absolutely be done right now, but doing so is a bit of a chore.

  • Elixir structs
  • Keyword lists

Fix lifetimes for NifEncoder and NifDecoder

At the moment NifEncoder can't encode borrowed values that are not statically lived. NifDecoder should also be able to return values borrowed directly from the BEAM (this is safe as long as the borrow is of the same lifetime as the NifEnv object).

I tried a few things to make this work, but I am a bit unsure how lifetimes work in conjunction with traits. More experimentation is needed, I should get back to this later.

Ability to init atoms from strings that are not statically lived?

Adding the ability to init atoms that don't have a static lifetime is trivial, but is it really wanted? The ability to create atoms on the fly is dangerous if abused, as atoms never get removed once created.

If this gets changed, do we want methods like ::map::make_ex_struct to also accept non statically lived strings?

versions out of sync

After I created a new Nif-module using rustler_mix 0.5.0, I do get a Cargo.toml referencing the following dependencies:

  • rustler = "0.12.0"
  • rustler_codegen = "0.12.0"

But both of them are only available as 0.11.0 on crates.io.

Can't compile rustler

One of the dependencies of rustler_codegen, synthax, is failing to compile for me with the following error:

   Compiling synthax v0.3.2
error: no associated item named `SpecialVarNt` found for type `syntax::parse::token::Token` in the current scope
   --> /home/name/.cargo/registry/src/github.com-1ecc6299db9ec823/synthax-0.3.2/src/expr.rs:172:13
    |
172 |             Token::SpecialVarNt(_) |
    |             ^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

error: Could not compile `synthax`.

I've tried compiling it with the following versions:

  • stable - rustc 1.12.1 (d4f39402a 2016-10-19)
  • nightly - rustc 1.14.0-nightly (7c69b0d5a 2016-11-01)

Add ATO Resources

I've been churning through many ideas on my Ruster project lately, and one that worked out really well and I think would be useful for Rustler is "Any Trait Object Resources" (ATO Resources)

In a nutshell, with a single resource type registration you can use any Rust type as a resource. The advantages are:

  • No need to pre-register types. You just start using them and they work.
  • No resource traits so no need for a wrapper type to get around trait orphan rules. For example Cell<String> can be used directly as a resource type.

So, if this fits in for Rustler I invite you to borrow the code; I will happily answer any questions about it. I'll also point out that the upcoming enif_select() function in OTP-20 will likely force a revisit of resources.

switch to rustup instead of multirust

The required version of rustc is only a week old, but still you are trying to use a version manager that is deprecated in favor of rustup for about half a year

impl Debug for NifTerm

This would be a killer feature. I don't see how to implement it, offhand. Especially since a NIF can't call back into Erlang code.

Bug: Deployed Elixir app breaks due to Rustler trying to link in Mix

Mix is only available in a dev environment, not a release environment, and it seems that Rustler is using Mix itself at: https://github.com/hansihe/Rustler/blob/master/rustler_mix/lib/rustler.ex#L14

This causes the app to fail when deployed. What should happen is that any generated nif's should be stored in the application-specific priv directory (which you can get via :code.priv_dir(:application_name), thus you might need to have the load_nif macro get passed in the application atom as well), then loaded from that directory by getting the private directory path (again via :code.priv_dir(:whatever_application_name)). Mix should never be accessed at any other time other then during compilation. :-)

Compile errors on OSX

create build directory and clone repos:

mkdir /tmp/rustler_test
cd /tmp/rustler_test 
git clone https://github.com/hansihe/Rustler.git
git clone https://github.com/hansihe/Rustler_Example.git
cd Rustler_Example/native
rustup override add nightly-2016-05-07-x86_64-apple-darwin

build:

cargo build

errors output:

    Updating registry `https://github.com/rust-lang/crates.io-index`
   Compiling libc v0.2.11
   Compiling easy-plugin v0.3.4
   Compiling lazy_static v0.1.16
   Compiling aster v0.16.0
   Compiling ruster_unsafe v0.4.0
   Compiling rustler v0.8.3 (file:///private/tmp/rustler_test/Rustler)
/private/tmp/rustler_test/Rustler/src/codegen_runtime.rs:8:5: 8:24 warning: use of deprecated item: renamed to `catch_unwind`, #[warn(deprecated)] on by default
/private/tmp/rustler_test/Rustler/src/codegen_runtime.rs:8 use std::panic::recover;
                                                               ^~~~~~~~~~~~~~~~~~~
/private/tmp/rustler_test/Rustler/src/codegen_runtime.rs:23:51: 23:58 warning: use of deprecated item: renamed to `catch_unwind`, #[warn(deprecated)] on by default
/private/tmp/rustler_test/Rustler/src/codegen_runtime.rs:23     let result: ::std::thread::Result<NIF_TERM> = recover(|| {
                                                                                                              ^~~~~~~
   Compiling rustler_codegen v0.8.3 (file:///private/tmp/rustler_test/Rustler/rustler_codegen)
/private/tmp/rustler_test/Rustler/rustler_codegen/src/resource.rs:66:13: 66:20 warning: unused variable: `builder`, #[warn(unused_variables)] on by default
/private/tmp/rustler_test/Rustler/rustler_codegen/src/resource.rs:66         let builder = ::aster::AstBuilder::new().span(span);
                                                                                 ^~~~~~~
/private/tmp/rustler_test/Rustler/rustler_codegen/src/resource.rs:66:13: 66:20 note: in this expansion of easy_plugin! (defined in /private/tmp/rustler_test/Rustler/rustler_codegen/src/lib.rs)
   Compiling native v0.1.0 (file:///private/tmp/rustler_test/Rustler_Example/native)
src/lib.rs:31:26: 31:35 warning: unused variable: `load_info`, #[warn(unused_variables)] on by default
src/lib.rs:31 fn on_load(env: &NifEnv, load_info: NifTerm) -> bool {
                                       ^~~~~~~~~
src/lib.rs:68:46: 68:50 warning: unused variable: `args`, #[warn(unused_variables)] on by default
src/lib.rs:68 fn make_resource_struct<'a>(env: &'a NifEnv, args: &Vec<NifTerm>) -> Result<NifTerm<'a>, NifError> {
                                                           ^~~~
src/lib.rs:80:37: 80:41 warning: unused variable: `args`, #[warn(unused_variables)] on by default
src/lib.rs:80 fn string_test<'a>(env: &'a NifEnv, args: &Vec<NifTerm>) -> Result<NifTerm<'a>, NifError> {
                                                  ^~~~
error: linking with `cc` failed: exit code: 1
note: "cc" "-m64" "-L" "/Users/hezhiqiang/.multirust/toolchains/nightly-2016-05-07-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib" "/private/tmp/rustler_test/Rustler_Example/native/target/debug/rust_nif.0.o" "-o" "/private/tmp/rustler_test/Rustler_Example/native/target/debug/librust_nif.dylib" "/private/tmp/rustler_test/Rustler_Example/native/target/debug/rust_nif.metadata.o" "-Wl,-dead_strip" "-nodefaultlibs" "-L" "/private/tmp/rustler_test/Rustler_Example/native/target/debug" "-L" "/private/tmp/rustler_test/Rustler_Example/native/target/debug/deps" "-L" "/Users/hezhiqiang/.multirust/toolchains/nightly-2016-05-07-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib" "-Wl,-force_load,/var/folders/m3/vn1yyrfx7l36cq6p8msc6wt80000gn/T/rustc.qQqNIUT1sO3i/librustler-73f06792a5236e6b.rlib" "-Wl,-force_load,/var/folders/m3/vn1yyrfx7l36cq6p8msc6wt80000gn/T/rustc.qQqNIUT1sO3i/libruster_unsafe-256b634055e24e72.rlib" "-Wl,-force_load,/var/folders/m3/vn1yyrfx7l36cq6p8msc6wt80000gn/T/rustc.qQqNIUT1sO3i/liblibc-6b483f9a7097e9a4.rlib" "-Wl,-force_load,/var/folders/m3/vn1yyrfx7l36cq6p8msc6wt80000gn/T/rustc.qQqNIUT1sO3i/liblazy_static-3a04918be71c80ee.rlib" "-Wl,-force_load,/var/folders/m3/vn1yyrfx7l36cq6p8msc6wt80000gn/T/rustc.qQqNIUT1sO3i/libstd-cb705824.rlib" "-Wl,-force_load,/var/folders/m3/vn1yyrfx7l36cq6p8msc6wt80000gn/T/rustc.qQqNIUT1sO3i/libcollections-cb705824.rlib" "-Wl,-force_load,/var/folders/m3/vn1yyrfx7l36cq6p8msc6wt80000gn/T/rustc.qQqNIUT1sO3i/librustc_unicode-cb705824.rlib" "-Wl,-force_load,/var/folders/m3/vn1yyrfx7l36cq6p8msc6wt80000gn/T/rustc.qQqNIUT1sO3i/librand-cb705824.rlib" "-Wl,-force_load,/var/folders/m3/vn1yyrfx7l36cq6p8msc6wt80000gn/T/rustc.qQqNIUT1sO3i/liballoc-cb705824.rlib" "-Wl,-force_load,/var/folders/m3/vn1yyrfx7l36cq6p8msc6wt80000gn/T/rustc.qQqNIUT1sO3i/liballoc_system-cb705824.rlib" "-Wl,-force_load,/var/folders/m3/vn1yyrfx7l36cq6p8msc6wt80000gn/T/rustc.qQqNIUT1sO3i/liblibc-cb705824.rlib" "-Wl,-force_load,/var/folders/m3/vn1yyrfx7l36cq6p8msc6wt80000gn/T/rustc.qQqNIUT1sO3i/libcore-cb705824.rlib" "-l" "System" "-l" "pthread" "-l" "c" "-l" "m" "-dynamiclib" "-Wl,-dylib" "-l" "compiler-rt"
note: Undefined symbols for architecture x86_64:
  "_enif_make_double", referenced from:
      rustler::wrapper::nif_interface::enif_make_double::h2955724b75cecc61 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      _$LT$f64$u20$as$u20$types..NifEncoder$GT$::encode::h1b4452714d6d4b10 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      _$LT$f32$u20$as$u20$types..NifEncoder$GT$::encode::h1c2ffc4881c2903f in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_get_ulong", referenced from:
      ruster_unsafe::enif_get_uint64::h6a6efcdf317b18c4 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      ruster_unsafe::enif_get_uint64::h6a6efcdf317b18c4 in libruster_unsafe-256b634055e24e72.rlib(ruster_unsafe-256b634055e24e72.0.o)
  "_enif_make_ulong", referenced from:
      ruster_unsafe::enif_make_uint64::ha34647124f8445ad in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      ruster_unsafe::enif_make_uint64::ha34647124f8445ad in libruster_unsafe-256b634055e24e72.rlib(ruster_unsafe-256b634055e24e72.0.o)
  "_enif_make_long", referenced from:
      ruster_unsafe::enif_make_int64::h19b8d04a69049b6a in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      ruster_unsafe::enif_make_int64::h19b8d04a69049b6a in libruster_unsafe-256b634055e24e72.rlib(ruster_unsafe-256b634055e24e72.0.o)
  "_enif_get_uint", referenced from:
      rustler::wrapper::nif_interface::enif_get_uint::hec8265bbe0c51e0e in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      _$LT$u32$u20$as$u20$types..NifDecoder$LT$$u27$a$GT$$GT$::decode::hc0ae96bb1a8a125d in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      _$LT$u8$u20$as$u20$types..NifDecoder$LT$$u27$a$GT$$GT$::decode::h121ec11005986bac in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      _$LT$u16$u20$as$u20$types..NifDecoder$LT$$u27$a$GT$$GT$::decode::hafda0f180ac6d8ca in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_get_int", referenced from:
      rustler::wrapper::nif_interface::enif_get_int::h55571de701762d16 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      _$LT$i32$u20$as$u20$types..NifDecoder$LT$$u27$a$GT$$GT$::decode::hfabef9a46f52c06d in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      _$LT$i8$u20$as$u20$types..NifDecoder$LT$$u27$a$GT$$GT$::decode::h233811501aa78314 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      _$LT$i16$u20$as$u20$types..NifDecoder$LT$$u27$a$GT$$GT$::decode::hb8e170e909e86d7d in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_make_int", referenced from:
      rustler::wrapper::nif_interface::enif_make_int::h7f7fa530497562c9 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      _$LT$i32$u20$as$u20$types..NifEncoder$GT$::encode::ha1c059136fd52252 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      _$LT$i8$u20$as$u20$types..NifEncoder$GT$::encode::hdf7d5ef7a23e6450 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      _$LT$i16$u20$as$u20$types..NifEncoder$GT$::encode::h4a4b9280ca8325e2 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_keep_resource", referenced from:
      rustler::wrapper::nif_interface::enif_keep_resource::h48259ec58ff12602 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_release_resource", referenced from:
      rustler::wrapper::nif_interface::enif_release_resource::h1bed4c24409b5214 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_make_resource", referenced from:
      rustler::wrapper::nif_interface::enif_make_resource::hbdef75d2a6655bea in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_alloc_resource", referenced from:
      rustler::wrapper::nif_interface::enif_alloc_resource::hcafb450777244b62 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_make_copy", referenced from:
      rustler::wrapper::nif_interface::enif_make_copy::h69214799fa3b9645 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_is_atom", referenced from:
      rustler::wrapper::nif_interface::enif_is_atom::h4c1e27a13c126b7e in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_get_list_cell", referenced from:
      rustler::wrapper::nif_interface::enif_get_list_cell::h1aab0cf182fd72cd in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_make_uint", referenced from:
      rustler::wrapper::nif_interface::enif_make_uint::h2f5d391bf13c10e8 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      _$LT$u32$u20$as$u20$types..NifEncoder$GT$::encode::h14d1119c142b082c in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      _$LT$u8$u20$as$u20$types..NifEncoder$GT$::encode::h39df33241c8c172a in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      _$LT$u16$u20$as$u20$types..NifEncoder$GT$::encode::hfd6c432f2c86f33a in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_make_map_update", referenced from:
      rustler::wrapper::nif_interface::enif_make_map_update::hb2ec93364aa738a7 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_get_map_value", referenced from:
      rustler::wrapper::nif_interface::enif_get_map_value::hf297cb65056a574d in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_make_map_put", referenced from:
      rustler::wrapper::nif_interface::enif_make_map_put::h9539e1550d86790f in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_open_resource_type", referenced from:
      rustler::wrapper::nif_interface::enif_open_resource_type::h196ab420ef77a458 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_make_new_map", referenced from:
      rustler::wrapper::nif_interface::enif_make_new_map::h04eb30055d0433ea in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_make_badarg", referenced from:
      rustler::wrapper::nif_interface::enif_make_badarg::hfd47f421776299e7 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_get_tuple", referenced from:
      rustler::wrapper::nif_interface::enif_get_tuple::h496dbde1a06b26fa in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_get_long", referenced from:
      ruster_unsafe::enif_get_int64::h7322dfab1d51cfe0 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      ruster_unsafe::enif_get_int64::h7322dfab1d51cfe0 in libruster_unsafe-256b634055e24e72.rlib(ruster_unsafe-256b634055e24e72.0.o)
  "_enif_get_map_size", referenced from:
      rustler::wrapper::nif_interface::enif_get_map_size::hd15a7dd43835f5fa in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_alloc_env", referenced from:
      rustler::wrapper::nif_interface::enif_alloc_env::h104eae5c02c87a95 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_make_binary", referenced from:
      rustler::wrapper::nif_interface::enif_make_binary::h4df56732cd29a1d9 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      rustler::binary::NifBinary::from_owned::hd68ef82867d453c3 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_alloc_binary", referenced from:
      rustler::wrapper::nif_interface::enif_alloc_binary::hc2f02f5b05daa256 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      rustler::binary::OwnedNifBinary::alloc::h83a4138714c8e953 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_release_binary", referenced from:
      rustler::wrapper::nif_interface::enif_release_binary::hcf385eda5649cf90 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      _$LT$binary..OwnedNifBinary$u20$as$u20$std..ops..Drop$GT$::drop::h6787ff98ae72ec84 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_get_list_length", referenced from:
      rustler::wrapper::nif_interface::enif_get_list_length::he2e2177223e5457e in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_is_empty_list", referenced from:
      rustler::wrapper::nif_interface::enif_is_empty_list::hf97958a62da19d09 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_get_double", referenced from:
      rustler::wrapper::nif_interface::enif_get_double::h8276570c21d114b6 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      _$LT$f64$u20$as$u20$types..NifDecoder$LT$$u27$a$GT$$GT$::decode::h6c5508c0ba78eb78 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      _$LT$f32$u20$as$u20$types..NifDecoder$LT$$u27$a$GT$$GT$::decode::ha05b75d016c816c4 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_raise_exception", referenced from:
      rustler::wrapper::nif_interface::enif_raise_exception::h72fc005bcd6c2a0a in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_is_list", referenced from:
      rustler::wrapper::nif_interface::enif_is_list::h76c50d412d0ac05d in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_make_tuple_from_array", referenced from:
      rustler::wrapper::nif_interface::enif_make_tuple_from_array::hd9d4712e9e6f5a51 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_make_map_remove", referenced from:
      rustler::wrapper::nif_interface::enif_make_map_remove::hffb914012c16730b in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_inspect_binary", referenced from:
      rustler::wrapper::nif_interface::enif_inspect_binary::h3e37ee6fd8a4fc76 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
      rustler::binary::NifBinary::from_term::ha2e3c6a8a7e79c98 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_get_resource", referenced from:
      rustler::wrapper::nif_interface::enif_get_resource::he472a38f7fa68a5b in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
  "_enif_make_atom_len", referenced from:
      rustler::wrapper::nif_interface::enif_make_atom_len::h45eb891df1a70a11 in librustler-73f06792a5236e6b.rlib(rustler-73f06792a5236e6b.0.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

error: aborting due to previous error
error: Could not compile `native`.

To learn more, run the command again with --verbose.

Failing Travis CI

It seems build is failing on Travis CI

running 2 tests
test NifTerm<'a>::decode_0 ... ignored
test list::NifListIterator_0 ... FAILED
failures:
---- list::NifListIterator_0 stdout ----
    error[E0412]: type name `NifListIterator` is undefined or not in scope
 --> <anon>:2:24
  |
2 |     let list_iterator: NifListIterator = try!(list_term.decode());
  |                        ^^^^^^^^^^^^^^^ undefined or not in scope
  |
  = help: no candidates by the name of `NifListIterator` found in your project; maybe you misspelled the name or forgot to import an external crate?
error[E0425]: unresolved name `list_term`
 --> <anon>:2:47
  |
2 |     let list_iterator: NifListIterator = try!(list_term.decode());
  |                                               ^^^^^^^^^ unresolved name
error[E0412]: type name `NifResult` is undefined or not in scope
 --> <anon>:4:13
  |
4 | let result: NifResult<Vec<i64>> = iter
  |             ^^^^^^^^^^^^^^^^^^^ undefined or not in scope
  |
  = help: no candidates by the name of `NifResult` found in your project; maybe you misspelled the name or forgot to import an external crate?
error[E0425]: unresolved name `iter`
 --> <anon>:4:35
  |
4 | let result: NifResult<Vec<i64>> = iter
  |                                   ^^^^ unresolved name
error[E0412]: type name `NifResult` is undefined or not in scope
 --> <anon>:9:16
  |
9 |     .collect::<NifResult<Vec<i64>>>();
  |                ^^^^^^^^^^^^^^^^^^^ undefined or not in scope
  |
  = help: no candidates by the name of `NifResult` found in your project; maybe you misspelled the name or forgot to import an external crate?
error[E0308]: mismatched types
 --> <anon>:2:42
  |
2 |     let list_iterator: NifListIterator = try!(list_term.decode());
  |                                          ^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `std::result::Result`
  |
  = note: expected type `()`
  = note:    found type `std::result::Result<_, _>`
  = note: this error originates in a macro outside of the current crate
error: aborting due to previous error(s)
thread 'list::NifListIterator_0' panicked at 'Box<Any>', ../src/librustc/session/mod.rs:185
note: Run with `RUST_BACKTRACE=1` for a backtrace.
failures:
    list::NifListIterator_0
test result: FAILED. 0 passed; 1 failed; 1 ignored; 0 measured
error: test failed
The command "cargo test --verbose" exited with 101.
Done. Your build exited with 1.

Feature request: support for ports

There's some code already for decoding ETF terms within Rust programs, which I'm hoping to use with Rustler (mostly relegating Rustler to compiling crates for Rust-implemented Erlang ports) in order to implement a port or two for an Elixir app (using this guide as a reference, albeit with Rust instead of Ruby). Would be nice to have a bit tighter integration on this front, though (in particular, being able to run something like mix rustler.port.new or mix rustler.new --port or something to generate the boilerplate like with NIF crates).

If I or someone else were to implement something like this for Rustler, would a PR be welcome? Or is this out of scope for Rustler?

Remove reexport of ruster_unsafe at crate root

To prevent brokenness and keep the possibility of migrating to our own bindings open in the future, all used erlang nif functions should be redefined in ::wrapper::nif_interface. This should be done with full type signatures.

Support NIF code upgrades

Hello.Thanks for the great project.

I found the error when I reload nif module on iex.

The on_load function for module Elixir.Test returned {{:badmatch,
  {:error, {:upgrade, 'Upgrade not supported by this NIF library.'}}},

Is that has any way to add/edit/export the upgrade function?

Thank you.

Rethink NifEnv

Right now there is a single NifEnv type, but two different main use cases for a NifEnv.
The use of a NifEnv is a env that is supplied with a NIF system call. This env is used to make terms, send messages and perform other operations in the process that called the NIF. This env type can never outlive the calling function, and should therefore have a lifetime that reflects that.
The second NifEnv type is a env that is allocated by user code, and that can be used across function calls. This env is fully owned by the user, and should not be limited in lifetime. A env such as this can be used to create terms belonging to that environment, and to send messages.

Potential challenges posed by this change would be that NifTerms should only be usable on the env it's created on.

Returning lists

As an exercice on rustler, I was trying to create a function fn(list) -> list. It seems this feature is not implemented yet, as I got an error every time I tried to encode a vector.

fn foo<'a>(env: &'a NifEnv, args: &Vec) -> NifResult<NifTerm<'a>> {
let iterator: NifListIterator = try!(args[0].decode());

let result: NifResult<Vec> = iterator
.map(|x| x.decode::())
.collect::<NifResult<Vec>>();

Ok(result.encode(env))
}

Is it possible to add this feature?

Redo error handling

I am not happy with the way NifError works at the moment. It should be revised/improved and integrated with already written code.

Release version 0.12.0

When I use "mix rustler.new" it generates skeleton where Cargo.toml references version 0.12.0 which is not yet released.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.