diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..e407f7c --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "luajit-sys" +version = "0.0.1" +authors = ["Aaron Loucks "] +edition = "2018" +keywords = ["lua", "luajit", "script"] + +[dependencies] +libc = "0.2" + +[build-dependencies] +cc = "1.0.40" +fs_extra = "1.1.0" \ No newline at end of file diff --git a/bindgen.sh b/bindgen.sh new file mode 100644 index 0000000..5dd058d --- /dev/null +++ b/bindgen.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +BINDGEN_VERSION=$(bindgen --version) + +bindgen -o src/ffi.rs \ + --raw-line "/// Generated with: ${BINDGEN_VERSION}" \ + --whitelist-var "LUA.*" \ + --whitelist-var "LUAJIT.*" \ + --whitelist-type "lua_.*" \ + --whitelist-type "luaL_.*" \ + --whitelist-function "lua_.*" \ + --whitelist-function "luaL_.*" \ + --whitelist-function "luaJIT.*" \ + --ctypes-prefix "libc" \ + --use-core \ + --impl-debug \ + ffi.h -- -I luajit/src + +sed -i -e 's/pub fn \(luaJIT_[^\(]*\)/\/\/\/ \n pub fn \1/' src/ffi.rs +sed -i -e 's/pub fn \(lua_[^\(]*\)/\/\/\/ \n pub fn \1/' src/ffi.rs +sed -i -e 's/pub fn \(luaL_[^\(]*\)/\/\/\/ \n pub fn \1/' src/ffi.rs +sed -i -e 's/pub type \(lua_[^\=]*\)/\/\/\/ \n pub type \1/' src/ffi.rs +sed -i -e 's/pub struct \(lua_[^\{]*\)/\/\/\/ \n pub struct \1/' src/ffi.rs +sed -i -e 's/pub struct \(luaL_[^\{]*\)/\/\/\/ \n pub struct \1/' src/ffi.rs + +cargo +stable fmt \ No newline at end of file diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..d96daef --- /dev/null +++ b/build.rs @@ -0,0 +1,71 @@ +use cc; +use fs_extra::dir; +use fs_extra::dir::CopyOptions; +use std::env; +use std::process::{Command, Stdio}; + +fn main() { + let target = env::var("TARGET").unwrap(); + + let luajit_dir = format!("{}\\luajit", env!("CARGO_MANIFEST_DIR")); + let out_dir = env::var("OUT_DIR").unwrap(); + let src_dir = format!("{}\\luajit\\src", out_dir); + + if cfg!(target_env = "msvc") { + let lib_path = format!("{}\\lua51.lib", &src_dir); + if !std::fs::metadata(&lib_path).is_ok() { + let cl_exe: cc::Tool = cc::windows_registry::find_tool(&target, "cl.exe").unwrap(); + let msvsbuild_bat = format!("{}\\msvcbuild.bat", &src_dir); + + let mut copy_options = CopyOptions::new(); + copy_options.overwrite = true; + dir::copy(&luajit_dir, &out_dir, ©_options).unwrap(); + + let mut buildcmd = Command::new(msvsbuild_bat); + for (name, value) in cl_exe.env() { + buildcmd.env(name, value); + } + buildcmd.env("Configuration", "Release"); + buildcmd.args(&["static"]); + buildcmd.current_dir(&src_dir); + buildcmd.stderr(Stdio::inherit()); + + let mut child = buildcmd.spawn().expect("failed to run msvcbuild.bat"); + + if !child + .wait() + .map(|status| status.success()) + .map_err(|_| false) + .unwrap_or(false) + { + panic!("Failed to build luajit"); + } + } + println!("cargo:rustc-link-search=native={}", src_dir); + println!("cargo:rustc-link-lib=static=lua51"); + } else { + let lib_path = format!("{}\\luajit.a", &src_dir); + if !std::fs::metadata(&lib_path).is_ok() { + let mut copy_options = CopyOptions::new(); + copy_options.overwrite = true; + dir::copy(&luajit_dir, &out_dir, ©_options).unwrap(); + + let mut buildcmd = Command::new("make"); + buildcmd.current_dir(&src_dir); + buildcmd.stderr(Stdio::inherit()); + + let mut child = buildcmd.spawn().expect("failed to run make"); + + if !child + .wait() + .map(|status| status.success()) + .map_err(|_| false) + .unwrap_or(false) + { + panic!("Failed to build luajit"); + } + } + println!("cargo:rustc-link-search=native={}", src_dir); + println!("cargo:rustc-link-lib=static=luajit"); + } +} diff --git a/examples/hello.lua b/examples/hello.lua new file mode 100644 index 0000000..87a4120 --- /dev/null +++ b/examples/hello.lua @@ -0,0 +1,3 @@ +print("Hello from lua") + +return 1 + 2 diff --git a/examples/lua.rs b/examples/lua.rs new file mode 100644 index 0000000..aa45cae --- /dev/null +++ b/examples/lua.rs @@ -0,0 +1,54 @@ +use std::env; +use std::ffi::{CStr, CString}; +use std::ptr; + +use luajit_sys as sys; + +unsafe fn run_script(script_name: String, script_src: String) { + let lua = sys::luaL_newstate(); + assert_ne!(lua, ptr::null_mut()); + sys::luaL_openlibs(lua); + let script_data = script_src.as_bytes(); + let script_name = CString::new(script_name).unwrap(); + let mut error = sys::luaL_loadbuffer( + lua, + script_data.as_ptr() as _, + script_data.len() as _, + script_name.as_ptr() as _, + ); + if error != 0 { + eprintln!("luaL_loadbuffer failed"); + } else { + error = sys::lua_pcall(lua, 0, 1, 0); + if error != 0 { + eprintln!("lua_pcall failed"); + } + } + let idx = sys::lua_gettop(lua); + if sys::lua_isnoneornil(lua, idx) != 1 { + let s = sys::lua_tostring(lua, idx); + assert_ne!(s, ptr::null(), "lua_tostring returned null"); + let result = CStr::from_ptr(s).to_string_lossy().to_string(); + println!("script result: {}", result); + } + sys::lua_close(lua); +} + +fn main() { + if let Some(script_name) = env::args().skip(1).next() { + let script_src = std::fs::read_to_string(&script_name) + .unwrap_or_else(|e| panic!("failed to read file: '{}' {:?}", &script_name, e)); + unsafe { + run_script(script_name, script_src); + } + } else { + println!( + "{} FILE", + env::current_exe() + .unwrap() + .file_name() + .unwrap() + .to_string_lossy() + ); + } +} diff --git a/ffi.h b/ffi.h new file mode 100644 index 0000000..a9fe40a --- /dev/null +++ b/ffi.h @@ -0,0 +1,4 @@ +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +#include "luajit.h" \ No newline at end of file diff --git a/src/ffi.rs b/src/ffi.rs new file mode 100644 index 0000000..76db086 --- /dev/null +++ b/src/ffi.rs @@ -0,0 +1,1113 @@ +/* automatically generated by rust-bindgen */ + +// Generated with: bindgen 0.49.1 + +pub const LUA_LDIR: &'static [u8; 7usize] = b"!\\lua\\\0"; +pub const LUA_CDIR: &'static [u8; 3usize] = b"!\\\0"; +pub const LUA_PATH_DEFAULT: &'static [u8; 38usize] = + b".\\?.lua;!\\lua\\?.lua;!\\lua\\?\\init.lua;\0"; +pub const LUA_CPATH_DEFAULT: &'static [u8; 30usize] = b".\\?.dll;!\\?.dll;!\\loadall.dll\0"; +pub const LUA_PATH: &'static [u8; 9usize] = b"LUA_PATH\0"; +pub const LUA_CPATH: &'static [u8; 10usize] = b"LUA_CPATH\0"; +pub const LUA_INIT: &'static [u8; 9usize] = b"LUA_INIT\0"; +pub const LUA_DIRSEP: &'static [u8; 2usize] = b"\\\0"; +pub const LUA_PATHSEP: &'static [u8; 2usize] = b";\0"; +pub const LUA_PATH_MARK: &'static [u8; 2usize] = b"?\0"; +pub const LUA_EXECDIR: &'static [u8; 2usize] = b"!\0"; +pub const LUA_IGMARK: &'static [u8; 2usize] = b"-\0"; +pub const LUA_PATH_CONFIG: &'static [u8; 11usize] = b"\\\n;\n?\n!\n-\n\0"; +pub const LUAI_MAXSTACK: u32 = 65500; +pub const LUAI_MAXCSTACK: u32 = 8000; +pub const LUAI_GCPAUSE: u32 = 200; +pub const LUAI_GCMUL: u32 = 200; +pub const LUA_MAXCAPTURES: u32 = 32; +pub const LUA_IDSIZE: u32 = 60; +pub const LUA_NUMBER_SCAN: &'static [u8; 4usize] = b"%lf\0"; +pub const LUA_NUMBER_FMT: &'static [u8; 6usize] = b"%.14g\0"; +pub const LUAI_MAXNUMBER2STR: u32 = 32; +pub const LUA_INTFRMLEN: &'static [u8; 2usize] = b"l\0"; +pub const LUA_VERSION: &'static [u8; 8usize] = b"Lua 5.1\0"; +pub const LUA_RELEASE: &'static [u8; 10usize] = b"Lua 5.1.4\0"; +pub const LUA_VERSION_NUM: u32 = 501; +pub const LUA_COPYRIGHT: &'static [u8; 41usize] = b"Copyright (C) 1994-2008 Lua.org, PUC-Rio\0"; +pub const LUA_AUTHORS: &'static [u8; 49usize] = + b"R. Ierusalimschy, L. H. de Figueiredo & W. Celes\0"; +pub const LUA_SIGNATURE: &'static [u8; 5usize] = b"\x1BLua\0"; +pub const LUA_MULTRET: i32 = -1; +pub const LUA_REGISTRYINDEX: i32 = -10000; +pub const LUA_ENVIRONINDEX: i32 = -10001; +pub const LUA_GLOBALSINDEX: i32 = -10002; +pub const LUA_OK: u32 = 0; +pub const LUA_YIELD: u32 = 1; +pub const LUA_ERRRUN: u32 = 2; +pub const LUA_ERRSYNTAX: u32 = 3; +pub const LUA_ERRMEM: u32 = 4; +pub const LUA_ERRERR: u32 = 5; +pub const LUA_TNONE: i32 = -1; +pub const LUA_TNIL: u32 = 0; +pub const LUA_TBOOLEAN: u32 = 1; +pub const LUA_TLIGHTUSERDATA: u32 = 2; +pub const LUA_TNUMBER: u32 = 3; +pub const LUA_TSTRING: u32 = 4; +pub const LUA_TTABLE: u32 = 5; +pub const LUA_TFUNCTION: u32 = 6; +pub const LUA_TUSERDATA: u32 = 7; +pub const LUA_TTHREAD: u32 = 8; +pub const LUA_MINSTACK: u32 = 20; +pub const LUA_GCSTOP: u32 = 0; +pub const LUA_GCRESTART: u32 = 1; +pub const LUA_GCCOLLECT: u32 = 2; +pub const LUA_GCCOUNT: u32 = 3; +pub const LUA_GCCOUNTB: u32 = 4; +pub const LUA_GCSTEP: u32 = 5; +pub const LUA_GCSETPAUSE: u32 = 6; +pub const LUA_GCSETSTEPMUL: u32 = 7; +pub const LUA_GCISRUNNING: u32 = 9; +pub const LUA_HOOKCALL: u32 = 0; +pub const LUA_HOOKRET: u32 = 1; +pub const LUA_HOOKLINE: u32 = 2; +pub const LUA_HOOKCOUNT: u32 = 3; +pub const LUA_HOOKTAILRET: u32 = 4; +pub const LUA_MASKCALL: u32 = 1; +pub const LUA_MASKRET: u32 = 2; +pub const LUA_MASKLINE: u32 = 4; +pub const LUA_MASKCOUNT: u32 = 8; +pub const LUA_FILEHANDLE: &'static [u8; 6usize] = b"FILE*\0"; +pub const LUA_COLIBNAME: &'static [u8; 10usize] = b"coroutine\0"; +pub const LUA_MATHLIBNAME: &'static [u8; 5usize] = b"math\0"; +pub const LUA_STRLIBNAME: &'static [u8; 7usize] = b"string\0"; +pub const LUA_TABLIBNAME: &'static [u8; 6usize] = b"table\0"; +pub const LUA_IOLIBNAME: &'static [u8; 3usize] = b"io\0"; +pub const LUA_OSLIBNAME: &'static [u8; 3usize] = b"os\0"; +pub const LUA_LOADLIBNAME: &'static [u8; 8usize] = b"package\0"; +pub const LUA_DBLIBNAME: &'static [u8; 6usize] = b"debug\0"; +pub const LUA_BITLIBNAME: &'static [u8; 4usize] = b"bit\0"; +pub const LUA_JITLIBNAME: &'static [u8; 4usize] = b"jit\0"; +pub const LUA_FFILIBNAME: &'static [u8; 4usize] = b"ffi\0"; +pub const LUA_ERRFILE: u32 = 6; +pub const LUA_NOREF: i32 = -2; +pub const LUA_REFNIL: i32 = -1; +pub const LUAJIT_VERSION: &'static [u8; 19usize] = b"LuaJIT 2.1.0-beta3\0"; +pub const LUAJIT_VERSION_NUM: u32 = 20100; +pub const LUAJIT_COPYRIGHT: &'static [u8; 34usize] = b"Copyright (C) 2005-2017 Mike Pall\0"; +pub const LUAJIT_URL: &'static [u8; 19usize] = b"http://luajit.org/\0"; +pub const LUAJIT_MODE_MASK: u32 = 255; +pub const LUAJIT_MODE_OFF: u32 = 0; +pub const LUAJIT_MODE_ON: u32 = 256; +pub const LUAJIT_MODE_FLUSH: u32 = 512; +pub type va_list = __builtin_va_list; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +/// +pub struct lua_State { + _unused: [u8; 0], +} +/// +pub type lua_CFunction = + ::core::option::Option libc::c_int>; +/// +pub type lua_Reader = ::core::option::Option< + unsafe extern "C" fn( + L: *mut lua_State, + ud: *mut libc::c_void, + sz: *mut usize, + ) -> *const libc::c_char, +>; +/// +pub type lua_Writer = ::core::option::Option< + unsafe extern "C" fn( + L: *mut lua_State, + p: *const libc::c_void, + sz: usize, + ud: *mut libc::c_void, + ) -> libc::c_int, +>; +/// +pub type lua_Alloc = ::core::option::Option< + unsafe extern "C" fn( + ud: *mut libc::c_void, + ptr: *mut libc::c_void, + osize: usize, + nsize: usize, + ) -> *mut libc::c_void, +>; +/// +pub type lua_Number = f64; +/// +pub type lua_Integer = isize; +extern "C" { + /// + pub fn lua_newstate(f: lua_Alloc, ud: *mut libc::c_void) -> *mut lua_State; +} +extern "C" { + /// + pub fn lua_close(L: *mut lua_State); +} +extern "C" { + /// + pub fn lua_newthread(L: *mut lua_State) -> *mut lua_State; +} +extern "C" { + /// + pub fn lua_atpanic(L: *mut lua_State, panicf: lua_CFunction) -> lua_CFunction; +} +extern "C" { + /// + pub fn lua_gettop(L: *mut lua_State) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_settop(L: *mut lua_State, idx: libc::c_int); +} +extern "C" { + /// + pub fn lua_pushvalue(L: *mut lua_State, idx: libc::c_int); +} +extern "C" { + /// + pub fn lua_remove(L: *mut lua_State, idx: libc::c_int); +} +extern "C" { + /// + pub fn lua_insert(L: *mut lua_State, idx: libc::c_int); +} +extern "C" { + /// + pub fn lua_replace(L: *mut lua_State, idx: libc::c_int); +} +extern "C" { + /// + pub fn lua_checkstack(L: *mut lua_State, sz: libc::c_int) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_xmove(from: *mut lua_State, to: *mut lua_State, n: libc::c_int); +} +extern "C" { + /// + pub fn lua_isnumber(L: *mut lua_State, idx: libc::c_int) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_isstring(L: *mut lua_State, idx: libc::c_int) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_iscfunction(L: *mut lua_State, idx: libc::c_int) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_isuserdata(L: *mut lua_State, idx: libc::c_int) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_type(L: *mut lua_State, idx: libc::c_int) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_typename(L: *mut lua_State, tp: libc::c_int) -> *const libc::c_char; +} +extern "C" { + /// + pub fn lua_equal(L: *mut lua_State, idx1: libc::c_int, idx2: libc::c_int) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_rawequal(L: *mut lua_State, idx1: libc::c_int, idx2: libc::c_int) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_lessthan(L: *mut lua_State, idx1: libc::c_int, idx2: libc::c_int) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_tonumber(L: *mut lua_State, idx: libc::c_int) -> lua_Number; +} +extern "C" { + /// + pub fn lua_tointeger(L: *mut lua_State, idx: libc::c_int) -> lua_Integer; +} +extern "C" { + /// + pub fn lua_toboolean(L: *mut lua_State, idx: libc::c_int) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_tolstring( + L: *mut lua_State, + idx: libc::c_int, + len: *mut usize, + ) -> *const libc::c_char; +} +extern "C" { + /// + pub fn lua_objlen(L: *mut lua_State, idx: libc::c_int) -> usize; +} +extern "C" { + /// + pub fn lua_tocfunction(L: *mut lua_State, idx: libc::c_int) -> lua_CFunction; +} +extern "C" { + /// + pub fn lua_touserdata(L: *mut lua_State, idx: libc::c_int) -> *mut libc::c_void; +} +extern "C" { + /// + pub fn lua_tothread(L: *mut lua_State, idx: libc::c_int) -> *mut lua_State; +} +extern "C" { + /// + pub fn lua_topointer(L: *mut lua_State, idx: libc::c_int) -> *const libc::c_void; +} +extern "C" { + /// + pub fn lua_pushnil(L: *mut lua_State); +} +extern "C" { + /// + pub fn lua_pushnumber(L: *mut lua_State, n: lua_Number); +} +extern "C" { + /// + pub fn lua_pushinteger(L: *mut lua_State, n: lua_Integer); +} +extern "C" { + /// + pub fn lua_pushlstring(L: *mut lua_State, s: *const libc::c_char, l: usize); +} +extern "C" { + /// + pub fn lua_pushstring(L: *mut lua_State, s: *const libc::c_char); +} +extern "C" { + /// + pub fn lua_pushvfstring( + L: *mut lua_State, + fmt: *const libc::c_char, + argp: va_list, + ) -> *const libc::c_char; +} +extern "C" { + /// + pub fn lua_pushfstring(L: *mut lua_State, fmt: *const libc::c_char, ...) + -> *const libc::c_char; +} +extern "C" { + /// + pub fn lua_pushcclosure(L: *mut lua_State, fn_: lua_CFunction, n: libc::c_int); +} +extern "C" { + /// + pub fn lua_pushboolean(L: *mut lua_State, b: libc::c_int); +} +extern "C" { + /// + pub fn lua_pushlightuserdata(L: *mut lua_State, p: *mut libc::c_void); +} +extern "C" { + /// + pub fn lua_pushthread(L: *mut lua_State) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_gettable(L: *mut lua_State, idx: libc::c_int); +} +extern "C" { + /// + pub fn lua_getfield(L: *mut lua_State, idx: libc::c_int, k: *const libc::c_char); +} +extern "C" { + /// + pub fn lua_rawget(L: *mut lua_State, idx: libc::c_int); +} +extern "C" { + /// + pub fn lua_rawgeti(L: *mut lua_State, idx: libc::c_int, n: libc::c_int); +} +extern "C" { + /// + pub fn lua_createtable(L: *mut lua_State, narr: libc::c_int, nrec: libc::c_int); +} +extern "C" { + /// + pub fn lua_newuserdata(L: *mut lua_State, sz: usize) -> *mut libc::c_void; +} +extern "C" { + /// + pub fn lua_getmetatable(L: *mut lua_State, objindex: libc::c_int) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_getfenv(L: *mut lua_State, idx: libc::c_int); +} +extern "C" { + /// + pub fn lua_settable(L: *mut lua_State, idx: libc::c_int); +} +extern "C" { + /// + pub fn lua_setfield(L: *mut lua_State, idx: libc::c_int, k: *const libc::c_char); +} +extern "C" { + /// + pub fn lua_rawset(L: *mut lua_State, idx: libc::c_int); +} +extern "C" { + /// + pub fn lua_rawseti(L: *mut lua_State, idx: libc::c_int, n: libc::c_int); +} +extern "C" { + /// + pub fn lua_setmetatable(L: *mut lua_State, objindex: libc::c_int) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_setfenv(L: *mut lua_State, idx: libc::c_int) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_call(L: *mut lua_State, nargs: libc::c_int, nresults: libc::c_int); +} +extern "C" { + /// + pub fn lua_pcall( + L: *mut lua_State, + nargs: libc::c_int, + nresults: libc::c_int, + errfunc: libc::c_int, + ) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_cpcall(L: *mut lua_State, func: lua_CFunction, ud: *mut libc::c_void) + -> libc::c_int; +} +extern "C" { + /// + pub fn lua_load( + L: *mut lua_State, + reader: lua_Reader, + dt: *mut libc::c_void, + chunkname: *const libc::c_char, + ) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_dump(L: *mut lua_State, writer: lua_Writer, data: *mut libc::c_void) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_yield(L: *mut lua_State, nresults: libc::c_int) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_resume(L: *mut lua_State, narg: libc::c_int) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_status(L: *mut lua_State) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_gc(L: *mut lua_State, what: libc::c_int, data: libc::c_int) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_error(L: *mut lua_State) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_next(L: *mut lua_State, idx: libc::c_int) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_concat(L: *mut lua_State, n: libc::c_int); +} +extern "C" { + /// + pub fn lua_getallocf(L: *mut lua_State, ud: *mut *mut libc::c_void) -> lua_Alloc; +} +extern "C" { + /// + pub fn lua_setallocf(L: *mut lua_State, f: lua_Alloc, ud: *mut libc::c_void); +} +extern "C" { + /// + pub fn lua_setlevel(from: *mut lua_State, to: *mut lua_State); +} +/// +pub type lua_Hook = + ::core::option::Option; +extern "C" { + /// + pub fn lua_getstack(L: *mut lua_State, level: libc::c_int, ar: *mut lua_Debug) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_getinfo( + L: *mut lua_State, + what: *const libc::c_char, + ar: *mut lua_Debug, + ) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_getlocal( + L: *mut lua_State, + ar: *const lua_Debug, + n: libc::c_int, + ) -> *const libc::c_char; +} +extern "C" { + /// + pub fn lua_setlocal( + L: *mut lua_State, + ar: *const lua_Debug, + n: libc::c_int, + ) -> *const libc::c_char; +} +extern "C" { + /// + pub fn lua_getupvalue( + L: *mut lua_State, + funcindex: libc::c_int, + n: libc::c_int, + ) -> *const libc::c_char; +} +extern "C" { + /// + pub fn lua_setupvalue( + L: *mut lua_State, + funcindex: libc::c_int, + n: libc::c_int, + ) -> *const libc::c_char; +} +extern "C" { + /// + pub fn lua_sethook( + L: *mut lua_State, + func: lua_Hook, + mask: libc::c_int, + count: libc::c_int, + ) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_gethook(L: *mut lua_State) -> lua_Hook; +} +extern "C" { + /// + pub fn lua_gethookmask(L: *mut lua_State) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_gethookcount(L: *mut lua_State) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_upvalueid(L: *mut lua_State, idx: libc::c_int, n: libc::c_int) -> *mut libc::c_void; +} +extern "C" { + /// + pub fn lua_upvaluejoin( + L: *mut lua_State, + idx1: libc::c_int, + n1: libc::c_int, + idx2: libc::c_int, + n2: libc::c_int, + ); +} +extern "C" { + /// + pub fn lua_loadx( + L: *mut lua_State, + reader: lua_Reader, + dt: *mut libc::c_void, + chunkname: *const libc::c_char, + mode: *const libc::c_char, + ) -> libc::c_int; +} +extern "C" { + /// + pub fn lua_version(L: *mut lua_State) -> *const lua_Number; +} +extern "C" { + /// + pub fn lua_copy(L: *mut lua_State, fromidx: libc::c_int, toidx: libc::c_int); +} +extern "C" { + /// + pub fn lua_tonumberx( + L: *mut lua_State, + idx: libc::c_int, + isnum: *mut libc::c_int, + ) -> lua_Number; +} +extern "C" { + /// + pub fn lua_tointegerx( + L: *mut lua_State, + idx: libc::c_int, + isnum: *mut libc::c_int, + ) -> lua_Integer; +} +extern "C" { + /// + pub fn lua_isyieldable(L: *mut lua_State) -> libc::c_int; +} +#[repr(C)] +#[derive(Copy, Clone)] +/// +pub struct lua_Debug { + pub event: libc::c_int, + pub name: *const libc::c_char, + pub namewhat: *const libc::c_char, + pub what: *const libc::c_char, + pub source: *const libc::c_char, + pub currentline: libc::c_int, + pub nups: libc::c_int, + pub linedefined: libc::c_int, + pub lastlinedefined: libc::c_int, + pub short_src: [libc::c_char; 60usize], + pub i_ci: libc::c_int, +} +#[test] +fn bindgen_test_layout_lua_Debug() { + assert_eq!( + ::core::mem::size_of::(), + 120usize, + concat!("Size of: ", stringify!(lua_Debug)) + ); + assert_eq!( + ::core::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(lua_Debug)) + ); + assert_eq!( + unsafe { &(*(::core::ptr::null::())).event as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(lua_Debug), + "::", + stringify!(event) + ) + ); + assert_eq!( + unsafe { &(*(::core::ptr::null::())).name as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(lua_Debug), + "::", + stringify!(name) + ) + ); + assert_eq!( + unsafe { &(*(::core::ptr::null::())).namewhat as *const _ as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(lua_Debug), + "::", + stringify!(namewhat) + ) + ); + assert_eq!( + unsafe { &(*(::core::ptr::null::())).what as *const _ as usize }, + 24usize, + concat!( + "Offset of field: ", + stringify!(lua_Debug), + "::", + stringify!(what) + ) + ); + assert_eq!( + unsafe { &(*(::core::ptr::null::())).source as *const _ as usize }, + 32usize, + concat!( + "Offset of field: ", + stringify!(lua_Debug), + "::", + stringify!(source) + ) + ); + assert_eq!( + unsafe { &(*(::core::ptr::null::())).currentline as *const _ as usize }, + 40usize, + concat!( + "Offset of field: ", + stringify!(lua_Debug), + "::", + stringify!(currentline) + ) + ); + assert_eq!( + unsafe { &(*(::core::ptr::null::())).nups as *const _ as usize }, + 44usize, + concat!( + "Offset of field: ", + stringify!(lua_Debug), + "::", + stringify!(nups) + ) + ); + assert_eq!( + unsafe { &(*(::core::ptr::null::())).linedefined as *const _ as usize }, + 48usize, + concat!( + "Offset of field: ", + stringify!(lua_Debug), + "::", + stringify!(linedefined) + ) + ); + assert_eq!( + unsafe { &(*(::core::ptr::null::())).lastlinedefined as *const _ as usize }, + 52usize, + concat!( + "Offset of field: ", + stringify!(lua_Debug), + "::", + stringify!(lastlinedefined) + ) + ); + assert_eq!( + unsafe { &(*(::core::ptr::null::())).short_src as *const _ as usize }, + 56usize, + concat!( + "Offset of field: ", + stringify!(lua_Debug), + "::", + stringify!(short_src) + ) + ); + assert_eq!( + unsafe { &(*(::core::ptr::null::())).i_ci as *const _ as usize }, + 116usize, + concat!( + "Offset of field: ", + stringify!(lua_Debug), + "::", + stringify!(i_ci) + ) + ); +} +impl ::core::fmt::Debug for lua_Debug { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + write ! ( f , "lua_Debug {{ event: {:?}, name: {:?}, namewhat: {:?}, what: {:?}, source: {:?}, currentline: {:?}, nups: {:?}, linedefined: {:?}, lastlinedefined: {:?}, short_src: [...], i_ci: {:?} }}" , self . event , self . name , self . namewhat , self . what , self . source , self . currentline , self . nups , self . linedefined , self . lastlinedefined , self . i_ci ) + } +} +extern "C" { + /// + pub fn luaL_openlibs(L: *mut lua_State); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +/// +pub struct luaL_Reg { + pub name: *const libc::c_char, + pub func: lua_CFunction, +} +#[test] +fn bindgen_test_layout_luaL_Reg() { + assert_eq!( + ::core::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(luaL_Reg)) + ); + assert_eq!( + ::core::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(luaL_Reg)) + ); + assert_eq!( + unsafe { &(*(::core::ptr::null::())).name as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(luaL_Reg), + "::", + stringify!(name) + ) + ); + assert_eq!( + unsafe { &(*(::core::ptr::null::())).func as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(luaL_Reg), + "::", + stringify!(func) + ) + ); +} +extern "C" { + /// + pub fn luaL_openlib( + L: *mut lua_State, + libname: *const libc::c_char, + l: *const luaL_Reg, + nup: libc::c_int, + ); +} +extern "C" { + /// + pub fn luaL_register(L: *mut lua_State, libname: *const libc::c_char, l: *const luaL_Reg); +} +extern "C" { + /// + pub fn luaL_getmetafield( + L: *mut lua_State, + obj: libc::c_int, + e: *const libc::c_char, + ) -> libc::c_int; +} +extern "C" { + /// + pub fn luaL_callmeta( + L: *mut lua_State, + obj: libc::c_int, + e: *const libc::c_char, + ) -> libc::c_int; +} +extern "C" { + /// + pub fn luaL_typerror( + L: *mut lua_State, + narg: libc::c_int, + tname: *const libc::c_char, + ) -> libc::c_int; +} +extern "C" { + /// + pub fn luaL_argerror( + L: *mut lua_State, + numarg: libc::c_int, + extramsg: *const libc::c_char, + ) -> libc::c_int; +} +extern "C" { + /// + pub fn luaL_checklstring( + L: *mut lua_State, + numArg: libc::c_int, + l: *mut usize, + ) -> *const libc::c_char; +} +extern "C" { + /// + pub fn luaL_optlstring( + L: *mut lua_State, + numArg: libc::c_int, + def: *const libc::c_char, + l: *mut usize, + ) -> *const libc::c_char; +} +extern "C" { + /// + pub fn luaL_checknumber(L: *mut lua_State, numArg: libc::c_int) -> lua_Number; +} +extern "C" { + /// + pub fn luaL_optnumber(L: *mut lua_State, nArg: libc::c_int, def: lua_Number) -> lua_Number; +} +extern "C" { + /// + pub fn luaL_checkinteger(L: *mut lua_State, numArg: libc::c_int) -> lua_Integer; +} +extern "C" { + /// + pub fn luaL_optinteger(L: *mut lua_State, nArg: libc::c_int, def: lua_Integer) -> lua_Integer; +} +extern "C" { + /// + pub fn luaL_checkstack(L: *mut lua_State, sz: libc::c_int, msg: *const libc::c_char); +} +extern "C" { + /// + pub fn luaL_checktype(L: *mut lua_State, narg: libc::c_int, t: libc::c_int); +} +extern "C" { + /// + pub fn luaL_checkany(L: *mut lua_State, narg: libc::c_int); +} +extern "C" { + /// + pub fn luaL_newmetatable(L: *mut lua_State, tname: *const libc::c_char) -> libc::c_int; +} +extern "C" { + /// + pub fn luaL_checkudata( + L: *mut lua_State, + ud: libc::c_int, + tname: *const libc::c_char, + ) -> *mut libc::c_void; +} +extern "C" { + /// + pub fn luaL_where(L: *mut lua_State, lvl: libc::c_int); +} +extern "C" { + /// + pub fn luaL_error(L: *mut lua_State, fmt: *const libc::c_char, ...) -> libc::c_int; +} +extern "C" { + /// + pub fn luaL_checkoption( + L: *mut lua_State, + narg: libc::c_int, + def: *const libc::c_char, + lst: *const *const libc::c_char, + ) -> libc::c_int; +} +extern "C" { + /// + pub fn luaL_ref(L: *mut lua_State, t: libc::c_int) -> libc::c_int; +} +extern "C" { + /// + pub fn luaL_unref(L: *mut lua_State, t: libc::c_int, ref_: libc::c_int); +} +extern "C" { + /// + pub fn luaL_loadfile(L: *mut lua_State, filename: *const libc::c_char) -> libc::c_int; +} +extern "C" { + /// + pub fn luaL_loadbuffer( + L: *mut lua_State, + buff: *const libc::c_char, + sz: usize, + name: *const libc::c_char, + ) -> libc::c_int; +} +extern "C" { + /// + pub fn luaL_loadstring(L: *mut lua_State, s: *const libc::c_char) -> libc::c_int; +} +extern "C" { + /// + pub fn luaL_newstate() -> *mut lua_State; +} +extern "C" { + /// + pub fn luaL_gsub( + L: *mut lua_State, + s: *const libc::c_char, + p: *const libc::c_char, + r: *const libc::c_char, + ) -> *const libc::c_char; +} +extern "C" { + /// + pub fn luaL_findtable( + L: *mut lua_State, + idx: libc::c_int, + fname: *const libc::c_char, + szhint: libc::c_int, + ) -> *const libc::c_char; +} +extern "C" { + /// + pub fn luaL_fileresult( + L: *mut lua_State, + stat: libc::c_int, + fname: *const libc::c_char, + ) -> libc::c_int; +} +extern "C" { + /// + pub fn luaL_execresult(L: *mut lua_State, stat: libc::c_int) -> libc::c_int; +} +extern "C" { + /// + pub fn luaL_loadfilex( + L: *mut lua_State, + filename: *const libc::c_char, + mode: *const libc::c_char, + ) -> libc::c_int; +} +extern "C" { + /// + pub fn luaL_loadbufferx( + L: *mut lua_State, + buff: *const libc::c_char, + sz: usize, + name: *const libc::c_char, + mode: *const libc::c_char, + ) -> libc::c_int; +} +extern "C" { + /// + pub fn luaL_traceback( + L: *mut lua_State, + L1: *mut lua_State, + msg: *const libc::c_char, + level: libc::c_int, + ); +} +extern "C" { + /// + pub fn luaL_setfuncs(L: *mut lua_State, l: *const luaL_Reg, nup: libc::c_int); +} +extern "C" { + /// + pub fn luaL_pushmodule(L: *mut lua_State, modname: *const libc::c_char, sizehint: libc::c_int); +} +extern "C" { + /// + pub fn luaL_testudata( + L: *mut lua_State, + ud: libc::c_int, + tname: *const libc::c_char, + ) -> *mut libc::c_void; +} +extern "C" { + /// + pub fn luaL_setmetatable(L: *mut lua_State, tname: *const libc::c_char); +} +#[repr(C)] +#[derive(Copy, Clone)] +/// +pub struct luaL_Buffer { + pub p: *mut libc::c_char, + pub lvl: libc::c_int, + pub L: *mut lua_State, + pub buffer: [libc::c_char; 512usize], +} +#[test] +fn bindgen_test_layout_luaL_Buffer() { + assert_eq!( + ::core::mem::size_of::(), + 536usize, + concat!("Size of: ", stringify!(luaL_Buffer)) + ); + assert_eq!( + ::core::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(luaL_Buffer)) + ); + assert_eq!( + unsafe { &(*(::core::ptr::null::())).p as *const _ as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(luaL_Buffer), + "::", + stringify!(p) + ) + ); + assert_eq!( + unsafe { &(*(::core::ptr::null::())).lvl as *const _ as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(luaL_Buffer), + "::", + stringify!(lvl) + ) + ); + assert_eq!( + unsafe { &(*(::core::ptr::null::())).L as *const _ as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(luaL_Buffer), + "::", + stringify!(L) + ) + ); + assert_eq!( + unsafe { &(*(::core::ptr::null::())).buffer as *const _ as usize }, + 24usize, + concat!( + "Offset of field: ", + stringify!(luaL_Buffer), + "::", + stringify!(buffer) + ) + ); +} +impl ::core::fmt::Debug for luaL_Buffer { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + write!( + f, + "luaL_Buffer {{ p: {:?}, lvl: {:?}, L: {:?}, buffer: [...] }}", + self.p, self.lvl, self.L + ) + } +} +extern "C" { + /// + pub fn luaL_buffinit(L: *mut lua_State, B: *mut luaL_Buffer); +} +extern "C" { + /// + pub fn luaL_prepbuffer(B: *mut luaL_Buffer) -> *mut libc::c_char; +} +extern "C" { + /// + pub fn luaL_addlstring(B: *mut luaL_Buffer, s: *const libc::c_char, l: usize); +} +extern "C" { + /// + pub fn luaL_addstring(B: *mut luaL_Buffer, s: *const libc::c_char); +} +extern "C" { + /// + pub fn luaL_addvalue(B: *mut luaL_Buffer); +} +extern "C" { + /// + pub fn luaL_pushresult(B: *mut luaL_Buffer); +} +pub const LUAJIT_MODE_ENGINE: _bindgen_ty_1 = 0; +pub const LUAJIT_MODE_DEBUG: _bindgen_ty_1 = 1; +pub const LUAJIT_MODE_FUNC: _bindgen_ty_1 = 2; +pub const LUAJIT_MODE_ALLFUNC: _bindgen_ty_1 = 3; +pub const LUAJIT_MODE_ALLSUBFUNC: _bindgen_ty_1 = 4; +pub const LUAJIT_MODE_TRACE: _bindgen_ty_1 = 5; +pub const LUAJIT_MODE_WRAPCFUNC: _bindgen_ty_1 = 16; +pub const LUAJIT_MODE_MAX: _bindgen_ty_1 = 17; +pub type _bindgen_ty_1 = i32; +extern "C" { + /// + pub fn luaJIT_setmode(L: *mut lua_State, idx: libc::c_int, mode: libc::c_int) -> libc::c_int; +} +pub type luaJIT_profile_callback = ::core::option::Option< + unsafe extern "C" fn( + data: *mut libc::c_void, + L: *mut lua_State, + samples: libc::c_int, + vmstate: libc::c_int, + ), +>; +extern "C" { + /// + pub fn luaJIT_profile_start( + L: *mut lua_State, + mode: *const libc::c_char, + cb: luaJIT_profile_callback, + data: *mut libc::c_void, + ); +} +extern "C" { + /// + pub fn luaJIT_profile_stop(L: *mut lua_State); +} +extern "C" { + /// + pub fn luaJIT_profile_dumpstack( + L: *mut lua_State, + fmt: *const libc::c_char, + depth: libc::c_int, + len: *mut usize, + ) -> *const libc::c_char; +} +extern "C" { + /// + pub fn luaJIT_version_2_1_0_beta3(); +} +pub type __builtin_va_list = *mut libc::c_char; diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..e0d799f --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,163 @@ +#![no_std] +#![allow(non_snake_case)] +#![allow(non_camel_case_types)] + +//! # LuaJIT 2.1 +//! +//! +//! +//! +//! +//! ## Performance considerations +//! +//! The _Not Yet Implemented_ guide documents which language features will be JIT compiled +//! into native machine code. +//! +//! + +mod ffi; +pub use ffi::*; + +use core::ptr; + +// These are defined as macros + +/// +#[inline] +pub unsafe fn lua_pop(L: *mut lua_State, idx: libc::c_int) { + lua_settop(L, -(idx) - 1) +} + +/// +#[inline] +pub unsafe fn lua_newtable(L: *mut lua_State) { + lua_createtable(L, 0, 0) +} + +/// +#[inline] +pub unsafe fn lua_register(L: *mut lua_State, name: *const libc::c_char, f: lua_CFunction) { + lua_pushcfunction(L, f); + lua_setglobal(L, name); +} + +/// +#[inline] +pub unsafe fn lua_pushcfunction(L: *mut lua_State, f: lua_CFunction) { + lua_pushcclosure(L, f, 0); +} + +/// +#[inline] +pub unsafe fn lua_strlen(L: *mut lua_State, idx: libc::c_int) -> usize { + lua_objlen(L, idx) +} + +/// +#[inline] +pub unsafe fn lua_isfunction(L: *mut lua_State, idx: libc::c_int) -> libc::c_int { + (lua_type(L, idx) == LUA_TFUNCTION as i32) as i32 +} + +/// +#[inline] +pub unsafe fn lua_istable(L: *mut lua_State, idx: libc::c_int) -> libc::c_int { + (lua_type(L, idx) == LUA_TTABLE as i32) as i32 +} + +/// +#[inline] +pub unsafe fn lua_islightuserdata(L: *mut lua_State, idx: libc::c_int) -> libc::c_int { + (lua_type(L, idx) == LUA_TLIGHTUSERDATA as i32) as i32 +} + +/// +#[inline] +pub unsafe fn lua_isnil(L: *mut lua_State, idx: libc::c_int) -> libc::c_int { + (lua_type(L, idx) == LUA_TNIL as i32) as i32 +} + +/// +#[inline] +pub unsafe fn lua_isboolean(L: *mut lua_State, idx: libc::c_int) -> libc::c_int { + (lua_type(L, idx) == LUA_TBOOLEAN as i32) as i32 +} + +/// +#[inline] +pub unsafe fn lua_isthread(L: *mut lua_State, idx: libc::c_int) -> libc::c_int { + (lua_type(L, idx) == LUA_TTHREAD as i32) as i32 +} + +/// +#[inline] +pub unsafe fn lua_isnone(L: *mut lua_State, idx: libc::c_int) -> libc::c_int { + (lua_type(L, idx) == LUA_TNONE as i32) as i32 +} + +/// +#[inline] +pub unsafe fn lua_isnoneornil(L: *mut lua_State, idx: libc::c_int) -> libc::c_int { + (lua_type(L, idx) <= 0) as i32 +} + +/// +#[inline] +pub unsafe fn lua_pushliteral(L: *mut lua_State, s: &str) { + lua_pushlstring(L, s.as_ptr() as _, s.len() as _); +} + +/// +#[inline] +pub unsafe fn lua_setglobal(L: *mut lua_State, k: *const libc::c_char) { + lua_setfield(L, LUA_GLOBALSINDEX, k); +} + +/// +#[inline] +pub unsafe fn lua_getglobal(L: *mut lua_State, k: *const libc::c_char) { + lua_getfield(L, LUA_GLOBALSINDEX, k) +} + +/// +#[inline] +pub unsafe fn lua_tostring(L: *mut lua_State, idx: libc::c_int) -> *const libc::c_char { + lua_tolstring(L, idx, ptr::null_mut()) +} + +// Additional compatibility items that are defined as macros + +/// `luaL_newstate()` +#[inline] +#[deprecated(since = "Lua 5.1", note = "replace with `luaL_newstate()`")] +pub unsafe fn lua_open() -> *mut lua_State { + luaL_newstate() +} + +/// `lua_pushvalue(L, LUA_REGISTRYINDEX)` +#[inline] +#[deprecated( + since = "Lua 5.1", + note = "replace with `lua_pushvalue(L, LUA_REGISTRYINDEX)`" +)] +pub unsafe fn lua_getregistry(L: *mut lua_State) { + lua_pushvalue(L, LUA_REGISTRYINDEX) +} + +/// `lua_gc(L, LUA_GCCOUNT as _, 0)` +#[inline] +#[deprecated( + since = "Lua 5.1", + note = "replace with `lua_gc(L, LUA_GCCOUNT as _, 0)`" +)] +pub unsafe fn lua_getgccount(L: *mut lua_State) -> libc::c_int { + lua_gc(L, LUA_GCCOUNT as _, 0) +} + +/// `lua_Reader` +#[deprecated(since = "Lua 5.1", note = "replace with `lua_Reader`")] +pub type lua_Chunkreader = lua_Reader; + +/// `lua_Writer` +#[deprecated(since = "Lua 5.1", note = "replace with `lua_Writer`")] +pub type lua_Chunkwriter = lua_Writer; diff --git a/tests/test.rs b/tests/test.rs new file mode 100644 index 0000000..e737156 --- /dev/null +++ b/tests/test.rs @@ -0,0 +1,40 @@ +use luajit_sys as sys; + +#[test] +fn run_script() { + use std::ffi::CStr; + use std::ptr; + + unsafe { + let lua = sys::luaL_newstate(); + assert_ne!(lua, ptr::null_mut()); + sys::luaL_openlibs(lua); + let script_data = b"return 1 + 2"; + let script_name = b"run_script\0"; + let mut error = sys::luaL_loadbuffer( + lua, + script_data.as_ptr() as _, + script_data.len() as _, + script_name.as_ptr() as _, + ); + if error != 0 { + eprintln!("luaL_loadbuffer failed"); + } else { + error = sys::lua_pcall(lua, 0, 1, 0); + if error != 0 { + eprintln!("lua_pcall failed"); + } + } + + let idx = sys::lua_gettop(lua); + println!("lua_gettop = {}", idx); + + let s = sys::lua_tostring(lua, idx); + assert_ne!(s, ptr::null(), "lua_tostring returned null"); + + let result = CStr::from_ptr(s).to_string_lossy().to_string(); + sys::lua_close(lua); + + assert_eq!("3", result); + } +}