Skip to content

Odin bindings to native Erlang libraries: erl_nif, erl_driver, erl_interface

License

Notifications You must be signed in to change notification settings

chriskdon/odin-erl

Repository files navigation

odin-erl

Version: v0.0.0-alpha (DO NOT USE ⚠️)

Issues MIT License

Table of Contents
  1. About The Project
  2. Getting Started
  3. Usage
  4. Project Structure
  5. TODO
  6. Contributing
  7. License

About the Project

Odin bindings to native Erlang libraries: erl_nif, erl_driver, erl_interface.

⚠️ None of this has been tested (yet). I initially created this project as a way to learn Odin, and get a deeper understanding of Erlang NIFs.

Built With

Odin Erlang ASDF

(back to top)

Getting Started

  1. Make sure ASDF is installed
  2. Install the Odin ASDF plugin: asdf plugin add odin
  3. Install the Erlang ASDF plugin: asdf plugin add erlang
  4. Install ASDF tools: asdf install
  5. make run_tests
    • The tests don't do much at the moment other than load and call a simple NIF written in Odin.

(back to top)

Usage

  1. Create a simple NIF in Odin

    // example_nif.odin
    
    package example_nif
    
    import "core:fmt"
    import "core:c"
    import "core:runtime"
    
    // Change to the path of wherever you've put the package
    import nif "../odin_erl_nif"
    import enif "../odin_erl_nif/erl_nif"
    
    // Name of the Erlang module the NIFs are being loaded into
    ERLANG_MODULE_NAME :: "example_nif"
    
    @export
    odin_add : enif.ErlangFFIPointer :  proc "c" (env: ^enif.ErlNifEnv, argc: c.int, argv: [^]enif.ERL_NIF_TERM) -> enif.ERL_NIF_TERM {
      x: c.int
      if (enif.get_int(env, argv[0], &x) == 0) {
        return enif.make_badarg(env);
      }
    
      y: c.int
      if (enif.get_int(env, argv[1], &y) == 0) {
        return enif.make_badarg(env);
      }
    
      return enif.make_int(env, x + y)
    }
    
    // List of functions to export as NIFs
    // {<erlang function name>, <arity>, <function pointer>, <flags>}
    nif_funcs := [?]enif.ErlNifFunc {
      {"odin_add", 2, odin_add, 0},
    }
    
    // Register the NIFs with Erlang
    @(init, private)
    _ :: proc() {
      nif.init(ERLANG_MODULE_NAME, nif_funcs[:])
    }
  2. Create an Erlang file to load the nif

    % example_nif.erl
    
    -module(example_nif).
    
    -export([odin_add/2]).
    
    -nifs([odin_add/2]).
    
    -on_load(init/0).
    
    init() ->
      ok = erlang:load_nif("./example_nif", 0).
    
    odin_add(_X, _Y) ->
      exit(nif_library_not_loaded).
  3. Compile Odin Library

    Get your Erlang major and minor version with: erlang:system_info(nif_version).

    odin build "<project folder>" \
      -define:ERL_NIF_MAJOR_VERSION=<nif_version major version> \
      -define:ERL_NIF_MINOR_VERSION=<nif_version minor version> \
      -build-mode:shared -no-entry-point \
      -extra-linker-flags="-dynamiclib -undefined dynamic_lookup -fpic" \
      -out="example_nif.so"
  4. Start an erlang shell with erl

    1> c(example_nif).
    2> example_nif:odin_add(2, 3).
    5
    

(back to top)

Project Structure

  • scripts
    • Helper scripts to build the project.
  • src
    • erl_nif
      • Low level bindings for erl_nif, and erL_driver. The functions and types in this packages should very closely follow the structure and format of the native libraries.
    • odin_erl_nif
      • High level helpers that make the low level erl_nif bindings nicer to work with.
  • tests
    • Test directory

(back to top)

TODO

  • 🚧 Create bindings for functions and types in erl_nif
    • 🚧 Functions
    • 🚧 Types
  • 🚧 Create bindings for functions and types in erl_driver
    • Functions
    • 🚧 Types
  • Create bindings for functions and types in erl_interface
    • Functions
    • Types
  • 🚧 Setup test framework
  • Write tests for all erl_nif functions
  • Write tests for all erl_driver functions
  • Write tests for all erl_interface functions
  • Create Odin allocator that uses the Erlang allocator
  • Add support for rebar3
  • 🚧 Create helper library that wraps the low level functions with a higher-level interface.

✅ - Complete

🚧 - Being worked on

See the open issues for a full list of proposed features (and known issues).

(back to top)

Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

(back to top)

License

Distributed under the MIT License. See LICENSE.txt for more information.

(back to top)

About

Odin bindings to native Erlang libraries: erl_nif, erl_driver, erl_interface

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages