tal-runtime/doc/extensions/index.md
2025-02-10 15:52:00 +02:00

213 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Extensions
LuaJIT is fully upwards-compatible with Lua 5.1. It supports all
[» standard Lua library functions](https://www.lua.org/manual/5.1/manual.html#5) and the full set of [» Lua/C API functions](https://www.lua.org/manual/5.1/manual.html#3).
LuaJIT is also fully ABI-compatible to Lua 5.1 at the linker/dynamic loader level. This means you can compile a C module against the standard Lua headers and load the same shared library from either Lua or LuaJIT.
LuaJIT extends the standard Lua VM with new functionality and adds several extension modules. Please note, this page is only about *functional* enhancements and not about performance enhancements, such as the optimized VM, the faster interpreter or the JIT compiler.
## Extensions Modules
LuaJIT comes with several built-in extension modules:
### `bit.*` — Bitwise operations
LuaJIT supports all bitwise operations as defined by [» Lua BitOp](https://bitop.luajit.org):
``` lua
bit.tobit bit.tohex bit.bnot bit.band bit.bor bit.bxor
bit.lshift bit.rshift bit.arshift bit.rol bit.ror bit.bswap
```
This module is a LuaJIT built-in — you don't need to download or install Lua BitOp. The Lua BitOp site has full documentation for all [» Lua BitOp API functions](https://bitop.luajit.org/api.html). The FFI adds support for [64 bit bitwise operations](./ext_ffi_semantics#cdata_arith), using the same API functions.
Please make sure to `require` the module before using any of its functions:
```lua
local bit = require "bit";
```
An already installed Lua BitOp module is ignored by LuaJIT. This way you can use bit operations from both Lua and LuaJIT on a shared installation.
### `ffi.*` — FFI library
The [FFI library](./ext_ffi) allows calling external C functions and the use of C data structures from pure Lua code.
### `jit.*` — JIT compiler control
The functions in this module [control the behavior of the JIT compiler engine](./ext_jit).
### C API extensions
LuaJIT adds some [extra functions to the Lua/C API](./ext_c_api).
### Profiler
LuaJIT has an [integrated profiler](./ext_profiler).
## Enhanced Standard Library Functions
### `xpcall(f, err [,args...])` passes arguments
Unlike the standard implementation in Lua 5.1, `xpcall()` passes any arguments after the error function to the function which is called in a protected context.
### `load*()` handle UTF-8 source code
Non-ASCII characters are handled transparently by the Lua source code parser. This allows the use of UTF-8 characters in identifiers and strings. A UTF-8 BOM is skipped at the start of the source code.
### `load*()` add a mode parameter
As an extension from Lua 5.2, the functions `loadstring()`, `loadfile()` and (new) `load()` add an optional `mode` parameter.
The default mode string is `"bt"`, which allows loading of both source code and bytecode. Use `"t"` to allow only source code or `"b"` to allow only bytecode to be loaded.
By default, the `load*` functions generate the native bytecode format. For cross-compilation purposes, add `W` to the mode string to force the 32 bit format and `X` to force the 64 bit format. Add both to force the opposite format. Note that non-native bytecode generated by `load*` cannot be run, but can still be passed to `string.dump`.
### `tostring()` etc. canonicalize NaN and ±Inf
All number-to-string conversions consistently convert non-finite numbers to the same strings on all platforms. NaN results in `"nan"`, positive infinity results in `"inf"` and negative infinity results in `"-inf"`.
### `tonumber()` etc. use builtin string to number conversion
All string-to-number conversions consistently convert integer and floating-point inputs in decimal, hexadecimal and binary on all platforms. `strtod()` is *not* used anymore, which avoids numerous problems with poor C library implementations. The builtin conversion function provides full precision according to the IEEE-754 standard, it works independently of the current locale and it supports hex floating-point numbers (e.g. `0x1.5p-3`).
### `string.dump(f [,mode])` generates portable bytecode
An extra argument has been added to `string.dump()`. If set to `true` or to a string which contains the character `s`, 'stripped' bytecode without debug information is generated. This speeds up later bytecode loading and reduces memory usage. See also the [`-b` command line option](./running#opt_b).
The generated bytecode is portable and can be loaded on any architecture that LuaJIT supports. However, the bytecode compatibility versions must match. Bytecode only stays compatible within a major+minor version (x.y.aaa → x.y.bbb), except for development branches. Foreign bytecode (e.g. from Lua 5.1) is incompatible and cannot be loaded.
Note: `LJ_GC64` mode requires a different frame layout, which implies a different, incompatible bytecode format between 32 bit and 64 bit ports. This may be rectified in the future. In the meantime, use the `W` and X [modes of the `load*` functions](#load-add-a-mode-parameter) for cross-compilation purposes.
Due to VM hardening, bytecode is not deterministic. Add `d` to the mode string to dump it in a deterministic manner: identical source code always gives a byte-for-byte identical bytecode dump. This feature is mainly useful for reproducible builds.
### `table.new(narray, nhash)` allocates a pre-sized table
An extra library function `table.new()` can be made available via `require("table.new")`. This creates a pre-sized table, just like the C API equivalent `lua_createtable()`. This is useful for big tables if the final table size is known and automatic table resizing is too expensive.
### `table.clear(tab)` clears a table
An extra library function `table.clear()` can be made available via `require("table.clear")`. This clears all keys and values from a table, but preserves the allocated array/hash sizes. This is useful when a table, which is linked from multiple places, needs to be cleared and/or when recycling a table for use by the same context. This avoids managing backlinks, saves an allocation and the overhead of incremental array/hash part growth.
Please note, this function is meant for very specific situations. In most cases it's better to replace the (usually single) link with a new table and let the GC do its work.
### Enhanced PRNG for `math.random()`
LuaJIT uses a Tausworthe PRNG with period 2^223 to implement `math.random()` and `math.randomseed()`. The quality of the PRNG results is much superior compared to the standard Lua implementation, which uses the platform-specific ANSI `rand()`.
The PRNG generates the same sequences from the same seeds on all platforms and makes use of all bits in the seed argument. `math.random()` without arguments generates 52 pseudo-random bits for every call. The result is uniformly distributed between 0.0 and 1.0. It's correctly scaled up and rounded for `math.random(n [,m])` to preserve uniformity.
Call `math.randomseed()` without any arguments to seed it from system entropy.
Important: Neither this nor any other PRNG based on the simplistic `math.random()` API is suitable for cryptographic use.
### `io.*` functions handle 64 bit file offsets
The file I/O functions in the standard `io.*` library handle 64 bit file offsets. In particular, this means it's possible to open files larger than 2 Gigabytes and to reposition or obtain the current file position for offsets beyond 2 GB (`fp:seek()` method).
### `debug.*` functions identify metamethods
`debug.getinfo()` and `lua_getinfo()` also return information about invoked metamethods. The `namewhat` field is set to `"metamethod"` and the `name` field has the name of the corresponding metamethod (e.g. `"__index"`).
## Fully Resumable VM
The LuaJIT VM is fully resumable. This means you can yield from a coroutine even across contexts, where this would not possible with the standard Lua 5.1 VM: e.g. you can yield across `pcall()` and `xpcall()`, across iterators and across metamethods.
## Extensions from Lua 5.2
LuaJIT supports some language and library extensions from Lua 5.2. Features that are unlikely to break existing code are unconditionally enabled:
- `goto` and `::labels::`.
- Hex escapes `'\x3F'` and `'\z'` escape in strings.
- `load(string|reader [, chunkname [,mode [,env]]])`.
- `loadstring()` is an alias for `load()`.
- `loadfile(filename [,mode [,env]])`.
- `math.log(x [,base])`.
- `string.rep(s, n [,sep])`.
- `string.format()`: `%q` reversible. `%s` checks `__tostring`. `%a` and `"%A` added.
- String matching pattern `%g` added.
- `io.read("*L")`.
- `io.lines()` and `file:lines()` process `io.read()` options.
- `os.exit(status|true|false [,close])`.
- `package.searchpath(name, path [, sep [, rep]])`.
- `package.loadlib(name, "*")`.
- `debug.getinfo()` returns `nparams` and `isvararg` for option `"u"`.
- `debug.getlocal()` accepts function instead of level.
- `debug.getlocal()` and `debug.setlocal()` accept negative indexes for varargs.
- `debug.getupvalue()` and `debug.setupvalue()` handle C functions.
- `debug.upvalueid()` and `debug.upvaluejoin()`.
- Lua/C API extensions: `lua_version()` `lua_upvalueid()` `lua_upvaluejoin()` `lua_loadx()` `lua_copy()` `lua_tonumberx()` `lua_tointegerx()` `luaL_fileresult()` `luaL_execresult()` `luaL_loadfilex()` `luaL_loadbufferx()` `luaL_traceback()` `luaL_setfuncs()` `luaL_pushmodule()` `luaL_newlibtable()` `luaL_newlib()` `luaL_testudata()` `luaL_setmetatable()`
- Command line option `-E`.
- Command line checks `__tostring` for errors.
Other features are only enabled, if LuaJIT is built with `-DLUAJIT_ENABLE_LUA52COMPAT`:
- `goto` is a keyword and not a valid variable name anymore.
- `break` can be placed anywhere. Empty statements (`;;`) are allowed.
- `__lt`, `__le` are invoked for mixed types.
- `__len` for tables. `rawlen()` library function.
- `pairs()` and `ipairs()` check for `__pairs` and `__ipairs`.
- `coroutine.running()` returns two results.
- `table.pack()` and `table.unpack()` (same as `unpack()`).
- `io.write()` and `file:write()` return file handle instead of `true`.
- `os.execute()` and `pipe:close()` return detailed exit status.
- `debug.setmetatable()` returns object.
- `debug.getuservalue()` and `debug.setuservalue()`.
- Remove `math.mod()`, `string.gfind()`.
- `package.searchers`.
- `module()` returns the module table.
Note: this provides only partial compatibility with Lua 5.2 at the
language and Lua library level. LuaJIT is API+ABI-compatible with
Lua 5.1, which prevents implementing features that would otherwise break
the Lua/C API and ABI (e.g. `_ENV`).
## Extensions from Lua 5.3
LuaJIT supports some extensions from Lua 5.3:
- Unicode escape `'\u{XX...}'` embeds the UTF-8 encoding in string literals.
- The argument table `arg` can be read (and modified) by `LUA_INIT` and `-e` chunks.
- `io.read()` and `file:read()` accept formats with or without a leading `*`.
- `assert()` accepts any type of error object.
- `table.move(a1, f, e, t [,a2])`.
- `coroutine.isyieldable()`.
- Lua/C API extensions: `lua_isyieldable()`
## C++ Exception Interoperability
LuaJIT has built-in support for interoperating with C++ exceptions. The
available range of features depends on the target platform and the
toolchain used to compile LuaJIT:
Platform | Compiler | Interoperability
----------------------------------|------------------|------------------
External frame unwinding | GCC, Clang, MSVC | **Full**
Internal frame unwinding + DWARF2 | GCC, Clang | **Limited**
Windows 64 bit | non-MSVC | **Limited**
Other platforms | Other compilers | **No**
**Full interoperability** means:
- C++ exceptions can be caught on the Lua side with `pcall()`, `lua_pcall()` etc.
- C++ exceptions will be converted to the generic Lua error `"C++ exception"`, unless you use the [C call wrapper](./ext_c_api#luajit_setmodel-idx-luajit_mode_wrapcfuncflag) feature.
- It's safe to throw C++ exceptions across non-protected Lua frames on the C stack. The contents of the C++ exception object pass through unmodified.
- Lua errors can be caught on the C++ side with `catch(...)`. The corresponding Lua error message can be retrieved from the Lua stack.
- Throwing Lua errors across C++ frames is safe. C++ destructors will be called.
**Limited interoperability** means:
- C++ exceptions can be caught on the Lua side with `pcall()`, `lua_pcall()` etc.
- C++ exceptions will be converted to the generic Lua error `"C++ exception"`, unless you use the [C call wrapper](./ext_c_api#luajit_setmodel-idx-luajit_mode_wrapcfuncflag) feature.
- C++ exceptions will be caught by non-protected Lua frames and are rethrown as a generic Lua error. The C++ exception object will be destroyed.
- Lua errors **cannot** be caught on the C++ side.
- Throwing Lua errors across C++ frames will **not** call C++ destructors.
**No interoperability** means:
- It's **not** safe to throw C++ exceptions across Lua frames.
- C++ exceptions **cannot** be caught on the Lua side.
- Lua errors **cannot** be caught on the C++ side.
- Throwing Lua errors across C++ frames will **not** call C++ destructors.