R_LANG(3) Library Functions Manual R_LANG(3)
NAME
r_lang — Scripting language support library for radare2
SYNOPSIS
Use this section to show the public header and the basic include needed to build against the r_lang API; it gives the minimal compile-time view of the library.
#include <r_lang.h>
DESCRIPTION
Readers will find here a concise overview of the goals and structure of the r_lang module: a plugin-driven runtime that lets radare2 host and run scripts and REPLs from multiple languages.
The r_lang library provides scripting language support for radare2 through a plugin-based system. It allows executing code in various programming languages within the radare2 environment, enabling automation, custom commands, and extensions.
At the heart of the API is struct r_lang_t, which 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 and cleanup.
INITIALIZATION
This section documents how to create and destroy an r_lang handle and how to associate runtime state (typically a pointer to an RCore instance) with it.
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);
EXECUTION
Use these calls to select a language plugin, execute code buffers, or invoke script files. The typical host (radare2) selects a plugin then calls one of the run helpers shown below.
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) are implemented per-plugin and can be entered via the generic prompt helper; this is the place 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 receive them via the argv helpers; the API lets hosts set argc/argv before invoking a file or an entry callback.
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 visible to scripts.
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.
•
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.
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
r_core(3), r_util(3) GNU September 21, 2025 R_LANG(3)