Janet 1.16.1-87f8fe1 Documentation
(Other Versions: 1.15.0 1.13.1 1.12.2 1.11.1 1.10.1 1.9.1 1.8.1 1.7.0 1.6.0 1.5.1 1.5.0 1.4.0 1.3.1 )


Janet can be embedded in a host program, usually written in C or C++, in several ways. The easiest way is to use the Janet's amalgamated build, which is a single giant C source file that can be copied into the host program's source tree. This method has many upsides, including simplicity and stability. You can also link to libjanet.so to include Janet as shared object.


In the context of embedding Janet in a program, we can call the larger program a client which usually uses the Janet library to run Janet source code. Most Janet clients have a number of things in common, especially some boilerplate required to get Janet code running.

The simplest Janet client will need to initialize the VM, load the core environment, run some Janet code, and then deinitialize the environent. A simple example program that does this is below.

#include <janet.h>

int main(int argc, const char *argv[]) {
    // Initialize the virtual machine. Do this before any calls to Janet functions.

    // Get the core janet environment. This contains all of the C functions in the core
    // as well as the code in src/boot/boot.janet.
    JanetTable *env = janet_core_env(NULL);

    // One of several ways to begin the Janet vm.
    janet_dostring(env, "(print `hello, world!`)", "main", NULL);

    // Use this to free all resources allocated by Janet.
    return 0;

Basic Janet Functions

JANET_API int janet_init(void);

Use this function to initialize global Janet state. This must be called once per thread if using Janet in a multithreaded environment, as all Janet global state is thread local by default.

JANET_API void janet_deinit(void);

Call this function to free all memory and resources managed by Janet.

JanetTable *janet_core_env(JanetTable *replacements);

Use this function to get the core environment for the Janet language. Replacements is an optional table that can be used to override some of the default bindings in the core environment. Usually, set to NULL.

int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char *sourcePath, Janet *out);

Use this function to compile and run some Janet source code from C. If you plan on running the code multiple times, there are more efficient options. However, for code that will only run once, this is a useful function.

int janet_dostring(JanetTable *env, const char *str, const char *sourcePath, Janet *out);

Similar to janet_dobytes, runs a null-terminated C string of Janet source code.

JanetSignal janet_continue(JanetFiber *fiber, Janet in, Janet *out);

Resumes a new or suspended fiber. Returns a signal that corresponds to the status of the fiber after execution, and places the return/signal value in out. When resuming a fiber, the value to resume with should be in the argument in, which corresponds to the second argument to the Janet resume function.

JanetSignal janet_pcall(JanetFunction *fun, int32_t argc, const Janet *argv, Janet *out, JanetFiber **f);

Invoke a function in a protected manner, catching any panics raised. Returns the resulting status code, as well as placing the return value in *out. The fiber pointer f is a pointer to a fiber pointer will contain the fiber used to run the function fun. If f is NULL, a new fiber will be created. Otherwise, Janet will use the fiber pointed to by f to run fun.

If no panics are raised, will return JANET_SIGNAL_OK. If an error is raised, will return JANET_SIGNAL_ERROR. Other signals will be returned as expected.

Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv);

Make a simple, re-entrant call back into the Janet interpreter from C. Try to put mostly simple, short running logic here as this suspends the garbage collector for the duration of the call. Functions called this way also must either return or error. Other signals will be coerced into an error.

void janet_stacktrace(JanetFiber *fiber, Janet err);

Print a janet stacktrace for the given fiber to stderr, or whatever is bound to the :err dynamic binding on the current fiber. You also must supply the return value or error message raised, as that is not tracked by the fiber itself.