C3nif (C3nif v0.2.0)

View Source

Write Erlang/Elixir NIFs in the C3 programming language.

C3nif provides inline NIF support for C3, allowing you to write high-performance native code with type-safe conversions, automatic resource management, and comprehensive error handling.

Basic Usage

Add use C3nif to your module with the :otp_app option, then use the ~n sigil (for "nif") to write inline C3 code:

defmodule MyNif do
  use C3nif, otp_app: :my_app

  ~n"""
  module mynif;

  import c3nif;
  import c3nif::env;
  import c3nif::term;

  <* nif: arity = 1 *>
  fn ErlNifTerm add_one(
      ErlNifEnv* raw_env,
      CInt argc,
      ErlNifTerm* argv
  ) {
      Env e = env::wrap(raw_env);
      Term arg0 = term::wrap(argv[0]);

      int? value = arg0.get_int(&e);
      if (catch err = value) {
          return term::make_badarg(&e).raw();
      }

      return term::make_int(&e, value + 1).raw();
  }
  """
end

Options

  • :otp_app - Required. The OTP application this module belongs to.

  • :c3_path - Optional. Path to external C3 source file instead of inline code.

  • :c3_sources - Optional. List of additional C3 source paths/globs to include (e.g., ["c3_src/mylib/src/**"]).

  • :nifs - Optional. List of NIF function specifications.

  • :precompiled - Optional. Enable precompiled NIF distribution. See C3nif.Precompiled and the precompilation guide. When set, the compile task will try to download and install a prebuilt shared library for the host triple before falling back to a local c3c build. Expects a keyword list with:

    • :base_url — URL prefix where .tar.gz artifacts are hosted
    • :version — version string used in artifact filenames
    • :checksums_path — absolute path to checksum-<version>.exs
    • :force_build (optional, default true) — fall back to source build if the precompiled fetch fails

C3 NIF Conventions

  • NIF functions use <* nif: arity = N *> doc comment annotations
  • Use dirty schedulers with <* nif: arity = N, dirty = cpu *> or dirty = io
  • Return ErlNifTerm from NIF functions
  • Use term::make_badarg() for argument errors

Summary

Functions

Returns the path to the C3 source directory.

Retrieves the C3 code from any given module that was compiled with C3nif.

Returns the NIF library file extension for the current platform.

Declares a string block to be included in the module's C3 source file.

Functions

c3_src_path()

Returns the path to the C3 source directory.

code(module)

Retrieves the C3 code from any given module that was compiled with C3nif.

nif_extension()

Returns the NIF library file extension for the current platform.

sigil_n(arg, list)

(macro)

Declares a string block to be included in the module's C3 source file.

The ~n sigil (for "nif") allows you to write inline C3 code that will be compiled into a NIF library.

Example

~n"""
module mymodule;

import c3nif;

fn ErlNifTerm my_nif(...) @nif {
    // NIF implementation
}
"""

Note: The sigil name is ~n (single letter) because Elixir only supports single-letter sigil names.