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. User_lang_use(..., "qjs")to select it andr_lang_run_string/r_lang_run_fileto execute code. β - C scripts: the C plugin compiles a
.cfile into a shared library, opens the resulting library, resolves anentrysymbol and calls it with the currentRCore *(stored inr_lang->user) and the configuredargc, argv. The C entry must have the signaturevoid 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
- alpine 3.24: radare2-doc 6.1.6-r0 Β· GPL-3.0-or-later AND LGPL-2.0-or-later AND LGPL-2.1-or-later
- arch rolling: radare2 6.2.2-1 Β· GPL-3.0-only AND LGPL-3.0-only
- nixos 26.05: radare2 6.1.8
- nixpkgs unstable: radare2 6.2.4
- opensuse-leap 16.0: radare2 6.2.2-bp160.1.1 Β· GPL-3.0-only AND LGPL-3.0-only
- opensuse-leap 16.0: radare2 6.2.2-bp160.1.1 Β· GPL-3.0-only AND LGPL-3.0-only
- opensuse-leap 16.0: radare2 6.2.2-bp160.1.1 Β· GPL-3.0-only AND LGPL-3.0-only
- opensuse-leap 16.0: radare2 6.2.2-bp160.1.1 Β· GPL-3.0-only AND LGPL-3.0-only
- ubuntu resolute: radare2 6.0.7+ds-1 Β· LGPL-3.0-only
- ubuntu stonking: radare2 6.1.8+ds-1 Β· LGPL-3.0-only
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms