nix-super/doc/external-api/README.md

122 lines
3.6 KiB
Markdown
Raw Normal View History

2023-08-07 18:54:31 +03:00
# Getting started
2024-01-10 12:58:35 +02:00
> **Warning** These bindings are **experimental**, which means they can change
> at any time or be removed outright; nevertheless the plan is to provide a
> stable external C API to the Nix language and the Nix store.
2023-08-07 18:54:31 +03:00
2024-01-10 12:58:35 +02:00
The language library allows evaluating Nix expressions and interacting with Nix
language values. The Nix store API is still rudimentary, and only allows
initialising and connecting to a store for the Nix language evaluator to
interact with.
Currently there are two ways to interface with the Nix language evaluator
programmatically:
1. Embedding the evaluator
2. Writing language plug-ins
2024-01-10 12:58:35 +02:00
Embedding means you link the Nix C libraries in your program and use them from
there. Adding a plug-in means you make a library that gets loaded by the Nix
language evaluator, specified through a configuration option.
2023-08-07 18:54:31 +03:00
2024-01-10 12:58:35 +02:00
Many of the components and mechanisms involved are not yet documented, therefore
please refer to the [Nix source code](https://github.com/NixOS/nix/) for
details. Additions to in-code documentation and the reference manual are highly
appreciated.
2024-01-10 12:58:35 +02:00
The following examples, for simplicity, don't include error handling. See the
[Handling errors](@ref errors) section for more information.
2023-08-07 18:54:31 +03:00
# Embedding the Nix Evaluator
2024-01-10 12:58:35 +02:00
In this example we programmatically start the Nix language evaluator with a
dummy store (that has no store paths and cannot be written to), and evaluate the
Nix expression `builtins.nixVersion`.
2023-08-07 18:54:31 +03:00
**main.c:**
2024-01-10 12:58:35 +02:00
2023-08-07 18:54:31 +03:00
```C
#include <nix_api_util.h>
#include <nix_api_expr.h>
#include <nix_api_value.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
2023-08-07 18:54:31 +03:00
2024-03-29 11:05:21 +02:00
// NOTE: This example lacks all error handling. Production code must check for
// errors, as some return values will be undefined.
2023-08-07 18:54:31 +03:00
void my_get_string_cb(const char * start, unsigned int n, void * user_data)
{
*((char **) user_data) = strdup(start);
}
int main()
{
nix_libexpr_init(NULL);
Store * store = nix_store_open(NULL, "dummy://", NULL);
EvalState * state = nix_state_create(NULL, NULL, store); // empty search path (NIX_PATH)
Value * value = nix_alloc_value(NULL, state);
nix_expr_eval_from_string(NULL, state, "builtins.nixVersion", ".", value);
nix_value_force(NULL, state, value);
2023-08-07 18:54:31 +03:00
char * version;
nix_get_string(NULL, value, my_get_string_cb, &version);
printf("Nix version: %s\n", version);
2023-08-07 18:54:31 +03:00
free(version);
nix_gc_decref(NULL, value);
nix_state_free(state);
nix_store_free(store);
return 0;
2023-08-07 18:54:31 +03:00
}
```
2024-01-09 23:51:39 +02:00
2023-08-07 18:54:31 +03:00
**Usage:**
2024-01-10 12:58:35 +02:00
```ShellSession
2023-08-07 18:54:31 +03:00
$ gcc main.c $(pkg-config nix-expr-c --libs --cflags) -o main
$ ./main
Nix version: 2.17
2023-08-07 18:54:31 +03:00
```
# Writing a Nix language plug-in
2024-01-10 12:58:35 +02:00
In this example we add a custom primitive operation (_primop_) to `builtins`. It
will increment the argument if it is an integer and throw an error otherwise.
2023-08-07 18:54:31 +03:00
**plugin.c:**
2024-01-10 12:58:35 +02:00
2023-08-07 18:54:31 +03:00
```C
#include <nix_api_util.h>
#include <nix_api_expr.h>
#include <nix_api_value.h>
2024-01-09 23:51:39 +02:00
2024-01-10 12:58:35 +02:00
void increment(void* user_data, nix_c_context* ctx, EvalState* state, Value** args, Value* v) {
2023-08-07 18:54:31 +03:00
nix_value_force(NULL, state, args[0]);
if (nix_get_type(NULL, args[0]) == NIX_TYPE_INT) {
2024-02-25 01:28:04 +02:00
nix_init_int(NULL, v, nix_get_int(NULL, args[0]) + 1);
2023-08-07 18:54:31 +03:00
} else {
nix_set_err_msg(ctx, NIX_ERR_UNKNOWN, "First argument should be an integer.");
2023-08-07 18:54:31 +03:00
}
}
2024-01-09 23:51:39 +02:00
2023-08-07 18:54:31 +03:00
void nix_plugin_entry() {
const char* args[] = {"n", NULL};
PrimOp *p = nix_alloc_primop(NULL, increment, 1, "increment", args, "Example custom built-in function: increments an integer", NULL);
2023-08-07 18:54:31 +03:00
nix_register_primop(NULL, p);
nix_gc_decref(NULL, p);
}
```
**Usage:**
2024-01-10 12:58:35 +02:00
```ShellSession
2023-08-07 18:54:31 +03:00
$ gcc plugin.c $(pkg-config nix-expr-c --libs --cflags) -shared -o plugin.so
$ nix --plugin-files ./plugin.so repl
nix-repl> builtins.increment 1
2
```