R_LANG(3)

πŸ’– R_LANG β€” the radare2 scripting-language glow-up πŸ’–

okay bestie, sit down, hydrate, because today we're talking about r_lang, aka the scripting language support library for radare2. it lives in the Library Functions Manual section, and it's genuinely iconic. no cap. πŸŽ€


✨ SYNOPSIS ✨

this bit is just showing you the public header and the absolute minimum include you need to build against the r_lang API β€” like, the tiniest little compile-time peek at the library. nothing more, nothing less. πŸ¦‹

#include <r_lang.h>

🌸 DESCRIPTION 🌸

here's the lowdown on what r_lang actually is and how it's built: it's a plugin-driven runtime that lets radare2 host and run scripts and REPLs from a whole bunch of different languages. it's giving "polyglot queen." πŸ‘‘

the r_lang library gives radare2 scripting language support through a plugin-based system. it lets you execute code in various programming languages right inside the radare2 environment β€” so automation, custom commands, and extensions are all on the table. πŸ”₯

at the very heart of the API is struct r_lang_t, and she manages loaded language plugins, user pointers, and execution sessions. language implementations register a struct r_lang_plugin_t, supplying callbacks for:

  • initialization
  • running code
  • running files
  • interactive prompts
  • cleanup

so yeah, every language plugin brings its own little callbacks and r_lang handles the hosting. teamwork makes the dream work fr fr 🫢


🌈 INITIALIZATION 🌈

this section is all about creating and destroying an r_lang handle, and how to associate runtime state with it (usually that's a pointer to an RCore instance, iykyk).

create a new language instance:

RLang *lang = r_lang_new();

set user pointer (usually RCore):

r_lang_set_user_ptr(lang, core);

free when done:

r_lang_free(lang);
πŸ’€ do not forget that free. she's not going to clean up after herself, bestie.

⭐ EXECUTION ⭐

these are the calls you use to select a language plugin, execute code buffers, or invoke script files. the typical host (that's radare2, hi) selects a plugin and then calls one of the run helpers below. it's a whole little routine. πŸ’…

select a language:

r_lang_use(lang, "qjs"); // QuickJS JavaScript

execute code string:

const char *code = "console.log('Hello from r2!');";
r_lang_run_string(lang, code);

execute code with length:

r_lang_run(lang, code, strlen(code));

execute script file:

r_lang_run_file(lang, "script.js");

πŸŽ€ INTERACTIVE MODE πŸŽ€

interactive features (REPLs!! the main character energy is unreal) are implemented per-plugin, and you enter them through the generic prompt helper. this is the spot to learn how to start a language REPL from the embedding application. 🧚

start interactive prompt:

r_lang_prompt(lang); // Interactive REPL

πŸ“ ARGUMENTS πŸ“

scripts that expect positional arguments get them through the argv helpers. the API lets hosts set argc/argv before invoking a file or an entry callback. order matters, okay? 😭

set command-line arguments for scripts:

char *argv[] = {"script.js", "arg1", "arg2"};
r_lang_set_argv(lang, 3, argv);

πŸ’œ DEFINITIONS πŸ’œ

use the definitions API to expose host pointers and typed variables to language runtimes. the host can add and remove named definitions that scripts can see. it's literally show-and-tell but for your host state. πŸ™ˆ

define variables accessible from scripts:

int value = 42;
r_lang_define(lang, "int", "my_var", &value);

remove definition:

r_lang_undef(lang, "my_var");

πŸ‘‘ LANGUAGES πŸ‘‘

this section highlights notable, supported language entry points rather than exhaustively listing every plugin. it focuses on the two integration styles commonly used by radare2: an embedded VM and native C plugin/script support. two very different vibes, both slaying.

  • JavaScript: a native QuickJS (qjs) plugin is available and is the canonical embedded scripting VM inside radare2. Use r_lang_use(..., "qjs") to select it and r_lang_run_string / r_lang_run_file to execute code. ⭐
  • C scripts: the C plugin compiles a .c file into a shared library, opens the resulting library, resolves an entry symbol and calls it with the current RCore * (stored in r_lang->user) and the configured argc, argv. The C entry must have the signature void entry(RCore *core, int argc, const char **argv). πŸ”₯

πŸ’… EXAMPLES πŸ’…

the examples below show common usage patterns observed in the radare2 core: invoking QuickJS code, running inline expressions via the #! hashbang helper, and how C scripts are compiled and invoked with the host RCore pointer. real-world rep, periodt.

execute JavaScript code:

#include <r_lang.h>

int main() {
    RLang *lang = r_lang_new();
    r_lang_use(lang, "qjs");

    const char *js_code = R"js(
        console.log("Hello from JavaScript!");
        var addr = 0x1000;
        console.log("Address: 0x" + addr.toString(16));
    )js";

    r_lang_run_string(lang, js_code);
    r_lang_free(lang);
    return 0;
}

define and use variables:

RLang *lang = r_lang_new();
int my_int = 12345;
r_lang_define(lang, "int", "global_var", &my_int);

r_lang_use(lang, "qjs");
r_lang_run_string(lang, "console.log('Value: ' + global_var);");

r_lang_free(lang);

execute script file:

r_lang_run_file(lang, "script.js");

hashbang and -e usage (used by the #! command in libr/core/cmd_hash.inc.c):

// the command handler implemented in libr/core/cmd_hash.inc.c parses `#!` lines
// and: selects the requested plugin (r_lang_get_by_name/r_lang_use_plugin),
// sets argv via r_lang_set_argv when file arguments are present, and either
// runs a file with r_lang_run_file or runs an expression with r_lang_run_string
// when `-e` is passed; expressions prefixed with `base64:` are decoded first.

C script example (how the C plugin runs code):

/* example.c */
#include <r_core.h>

void entry(RCore *core, int argc, const char **argv) {
    char *s = r_core_cmd_str (core, "?E hello world");
    printf("%s", s);
    free (s);
}

/* The C plugin will compile this file to a shared library and call `entry` with
   the host RCore pointer (r_lang->user) and any argv configured via
   r_lang_set_argv(). */

πŸ¦‹ SEE ALSO πŸ¦‹

go read those too, bestie, they're the supporting cast and they ate. πŸ’–


and that's the whole page!! this one came from the Debian fam, dated September 21, 2025, and it's the R_LANG(3) manual β€” so go forth and script, queen. πŸŽ€βœ¨πŸ‘‘πŸ’…

πŸ“¦ where this page comes from