Add build script and generated ffi
This commit is contained in:
parent
50f832a25d
commit
f144a4ff6a
9 changed files with 1487 additions and 0 deletions
13
Cargo.toml
Normal file
13
Cargo.toml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
[package]
|
||||||
|
name = "luajit-sys"
|
||||||
|
version = "0.0.1"
|
||||||
|
authors = ["Aaron Loucks <aloucks@cofront.net>"]
|
||||||
|
edition = "2018"
|
||||||
|
keywords = ["lua", "luajit", "script"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libc = "0.2"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
cc = "1.0.40"
|
||||||
|
fs_extra = "1.1.0"
|
26
bindgen.sh
Normal file
26
bindgen.sh
Normal file
|
@ -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_[^\(]*\)/\/\/\/ <https:\/\/luajit.org\/ext_c_api.html> \n pub fn \1/' src/ffi.rs
|
||||||
|
sed -i -e 's/pub fn \(lua_[^\(]*\)/\/\/\/ <https\:\/\/www.lua.org\/manual\/5.1\/manual.html#\1> \n pub fn \1/' src/ffi.rs
|
||||||
|
sed -i -e 's/pub fn \(luaL_[^\(]*\)/\/\/\/ <https\:\/\/www.lua.org\/manual\/5.1\/manual.html#\1> \n pub fn \1/' src/ffi.rs
|
||||||
|
sed -i -e 's/pub type \(lua_[^\=]*\)/\/\/\/ <https\:\/\/www.lua.org\/manual\/5.1\/manual.html#\1> \n pub type \1/' src/ffi.rs
|
||||||
|
sed -i -e 's/pub struct \(lua_[^\{]*\)/\/\/\/ <https\:\/\/www.lua.org\/manual\/5.1\/manual.html#\1> \n pub struct \1/' src/ffi.rs
|
||||||
|
sed -i -e 's/pub struct \(luaL_[^\{]*\)/\/\/\/ <https\:\/\/www.lua.org\/manual\/5.1\/manual.html#\1> \n pub struct \1/' src/ffi.rs
|
||||||
|
|
||||||
|
cargo +stable fmt
|
71
build.rs
Normal file
71
build.rs
Normal file
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
3
examples/hello.lua
Normal file
3
examples/hello.lua
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
print("Hello from lua")
|
||||||
|
|
||||||
|
return 1 + 2
|
54
examples/lua.rs
Normal file
54
examples/lua.rs
Normal file
|
@ -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()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
4
ffi.h
Normal file
4
ffi.h
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#include "lua.h"
|
||||||
|
#include "lualib.h"
|
||||||
|
#include "lauxlib.h"
|
||||||
|
#include "luajit.h"
|
1113
src/ffi.rs
Normal file
1113
src/ffi.rs
Normal file
File diff suppressed because it is too large
Load diff
163
src/lib.rs
Normal file
163
src/lib.rs
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
#![no_std]
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
|
//! # LuaJIT 2.1
|
||||||
|
//!
|
||||||
|
//! <http://luajit.org>
|
||||||
|
//!
|
||||||
|
//! <http://www.lua.org/manual/5.1/manual.html>
|
||||||
|
//!
|
||||||
|
//! ## Performance considerations
|
||||||
|
//!
|
||||||
|
//! The _Not Yet Implemented_ guide documents which language features will be JIT compiled
|
||||||
|
//! into native machine code.
|
||||||
|
//!
|
||||||
|
//! <http://wiki.luajit.org/NYI>
|
||||||
|
|
||||||
|
mod ffi;
|
||||||
|
pub use ffi::*;
|
||||||
|
|
||||||
|
use core::ptr;
|
||||||
|
|
||||||
|
// These are defined as macros
|
||||||
|
|
||||||
|
/// <https://www.lua.org/manual/5.1/manual.html#lua_pop>
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn lua_pop(L: *mut lua_State, idx: libc::c_int) {
|
||||||
|
lua_settop(L, -(idx) - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://www.lua.org/manual/5.1/manual.html#lua_newtable>
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn lua_newtable(L: *mut lua_State) {
|
||||||
|
lua_createtable(L, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://www.lua.org/manual/5.1/manual.html#lua_register>
|
||||||
|
#[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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://www.lua.org/manual/5.1/manual.html#lua_pushcfunction>
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn lua_pushcfunction(L: *mut lua_State, f: lua_CFunction) {
|
||||||
|
lua_pushcclosure(L, f, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://www.lua.org/manual/5.1/manual.html#lua_strlen>
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn lua_strlen(L: *mut lua_State, idx: libc::c_int) -> usize {
|
||||||
|
lua_objlen(L, idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://www.lua.org/manual/5.1/manual.html#lua_isfunction>
|
||||||
|
#[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
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://www.lua.org/manual/5.1/manual.html#lua_istable>
|
||||||
|
#[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
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://www.lua.org/manual/5.1/manual.html#lua_islightuserdata>
|
||||||
|
#[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
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://www.lua.org/manual/5.1/manual.html#lua_isnil>
|
||||||
|
#[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
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://www.lua.org/manual/5.1/manual.html#lua_isboolean>
|
||||||
|
#[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
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://www.lua.org/manual/5.1/manual.html#lua_isthread>
|
||||||
|
#[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
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://www.lua.org/manual/5.1/manual.html#lua_isnone>
|
||||||
|
#[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
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://www.lua.org/manual/5.1/manual.html#lua_isnoneornil>
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn lua_isnoneornil(L: *mut lua_State, idx: libc::c_int) -> libc::c_int {
|
||||||
|
(lua_type(L, idx) <= 0) as i32
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://www.lua.org/manual/5.1/manual.html#lua_pushliteral>
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn lua_pushliteral(L: *mut lua_State, s: &str) {
|
||||||
|
lua_pushlstring(L, s.as_ptr() as _, s.len() as _);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://www.lua.org/manual/5.1/manual.html#lua_setglobal>
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn lua_setglobal(L: *mut lua_State, k: *const libc::c_char) {
|
||||||
|
lua_setfield(L, LUA_GLOBALSINDEX, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://www.lua.org/manual/5.1/manual.html#lua_getglobal>
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn lua_getglobal(L: *mut lua_State, k: *const libc::c_char) {
|
||||||
|
lua_getfield(L, LUA_GLOBALSINDEX, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://www.lua.org/manual/5.1/manual.html#lua_tostring>
|
||||||
|
#[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;
|
40
tests/test.rs
Normal file
40
tests/test.rs
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue