Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix individual library open functions #147

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 97 additions & 10 deletions hlua/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,84 +499,100 @@ impl<'lua> Lua<'lua> {
unsafe { ffi::luaL_openlibs(self.lua.0) }
}

// Helper to import library
fn open_helper(&mut self, modname: &str, func: ffi::lua_CFunction2) {
unsafe {
// No need to handle error since input is hardcoded
// See https://doc.rust-lang.org/std/ffi/struct.CString.html#method.new
let name = CString::new(modname).unwrap();
ffi::luaL_requiref(
self.lua.0,
name.as_ptr(),
func,
1
);
ffi::lua_pop(self.lua.0, 1);
}
}

/// Opens base library.
///
/// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_base
#[inline]
pub fn open_base(&mut self) {
unsafe { ffi::luaopen_base(self.lua.0) }
self.open_helper("_G", ffi::luaopen_base);
}

/// Opens bit32 library.
///
/// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_bit32
#[inline]
pub fn open_bit32(&mut self) {
unsafe { ffi::luaopen_bit32(self.lua.0) }
self.open_helper("bit32", ffi::luaopen_bit32);
}

/// Opens coroutine library.
///
/// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_coroutine
#[inline]
pub fn open_coroutine(&mut self) {
unsafe { ffi::luaopen_coroutine(self.lua.0) }
self.open_helper("coroutine", ffi::luaopen_coroutine);
}

/// Opens debug library.
///
/// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_debug
#[inline]
pub fn open_debug(&mut self) {
unsafe { ffi::luaopen_debug(self.lua.0) }
self.open_helper("debug", ffi::luaopen_debug);
}

/// Opens io library.
///
/// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_io
#[inline]
pub fn open_io(&mut self) {
unsafe { ffi::luaopen_io(self.lua.0) }
self.open_helper("io", ffi::luaopen_io);
}

/// Opens math library.
///
/// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_math
#[inline]
pub fn open_math(&mut self) {
unsafe { ffi::luaopen_math(self.lua.0) }
self.open_helper("math", ffi::luaopen_math);
}

/// Opens os library.
///
/// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_os
#[inline]
pub fn open_os(&mut self) {
unsafe { ffi::luaopen_os(self.lua.0) }
self.open_helper("os", ffi::luaopen_os);
}

/// Opens package library.
///
/// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_package
#[inline]
pub fn open_package(&mut self) {
unsafe { ffi::luaopen_package(self.lua.0) }
self.open_helper("package", ffi::luaopen_package);
}

/// Opens string library.
///
/// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_string
#[inline]
pub fn open_string(&mut self) {
unsafe { ffi::luaopen_string(self.lua.0) }
self.open_helper("string", ffi::luaopen_string);
}

/// Opens table library.
///
/// https://www.lua.org/manual/5.2/manual.html#pdf-luaopen_table
#[inline]
pub fn open_table(&mut self) {
unsafe { ffi::luaopen_table(self.lua.0) }
self.open_helper("table", ffi::luaopen_table);
}

/// Executes some Lua code in the context.
Expand Down Expand Up @@ -911,6 +927,7 @@ impl<L> Drop for PushGuard<L> {
mod tests {
use Lua;
use LuaError;
use LuaTable;

#[test]
fn open_base_opens_base_library() {
Expand Down Expand Up @@ -939,4 +956,74 @@ mod tests {
lua.open_string();
lua.open_table();
}

#[test]
fn opening_base() {
let mut lua = Lua::new();
lua.open_base();
let _: LuaTable<_> = lua.get("_G").unwrap();
}

#[test]
fn opening_bit32() {
let mut lua = Lua::new();
lua.open_bit32();
let _: LuaTable<_> = lua.get("bit32").unwrap();
}

#[test]
fn opening_coroutine() {
let mut lua = Lua::new();
lua.open_coroutine();
let _: LuaTable<_> = lua.get("coroutine").unwrap();
}

#[test]
fn opening_debug() {
let mut lua = Lua::new();
lua.open_debug();
let _: LuaTable<_> = lua.get("debug").unwrap();
}

#[test]
fn opening_io() {
let mut lua = Lua::new();
lua.open_io();
let _: LuaTable<_> = lua.get("io").unwrap();
}

#[test]
fn opening_math() {
let mut lua = Lua::new();
lua.open_math();
let _: LuaTable<_> = lua.get("math").unwrap();
}

#[test]
fn opening_os() {
let mut lua = Lua::new();
lua.open_os();
let _: LuaTable<_> = lua.get("os").unwrap();
}

#[test]
fn opening_package() {
let mut lua = Lua::new();
lua.open_package();
let _: LuaTable<_> = lua.get("package").unwrap();
}

#[test]
fn opening_string() {
let mut lua = Lua::new();
lua.open_string();
let _: LuaTable<_> = lua.get("string").unwrap();
}

#[test]
fn opening_table() {
let mut lua = Lua::new();
lua.open_table();
let _: LuaTable<_> = lua.get("table").unwrap();
}
}
3 changes: 3 additions & 0 deletions lua52-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub const LUA_ERRERR: c_int = 6;
pub struct lua_State;

pub type lua_CFunction = extern "C" fn(L: *mut lua_State) -> c_int;
pub type lua_CFunction2 = unsafe extern "C" fn(*mut lua_State);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why I needed to create this type, I see other FFI declerations use the lua_CFunction type, and the docs for requiref don't seem any different to me.

Copy link
Owner

@tomaka tomaka May 7, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not change the definition of luaL_requiref to use lua_CFunction instead?

EDIT: Ah nevermind, I see. I suppose you could also cast the function pointers instead.
I'd prefer if bindings remained identical to the C header.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is basically what I cobbled together from reading Rust's error messages and trying a bunch of random things. I really don't have the expertise to go much further.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should change open_helper to accept a unsafe extern "C" fn(*mut lua_State) instead of a ffi::lua_CFunction2 (which allows you to remove lua_CFunction2 from the bindings).

Then in open_helper you should be able to do something like func as ffi::lua_CFunction. If it doesn't work, use mem::transmute(func). It's the last resort solution, but at least it would compile.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That still won't help the luaL_requiref binding that needs the lua_CFunction2 though?


pub type lua_Reader = extern "C" fn(L: *mut lua_State, ud: *mut libc::c_void, sz: *mut libc::size_t) -> *const libc::c_char;
pub type lua_Writer = extern "C" fn(L: *mut lua_State, p: *const libc::c_void, sz: libc::size_t, ud: *mut libc::c_void) -> libc::c_int;
Expand Down Expand Up @@ -223,6 +224,8 @@ extern "C" {
pub fn lua_gethookmask(L: *mut lua_State) -> c_int;
pub fn lua_gethookcount(L: *mut lua_State) -> c_int;

pub fn luaL_requiref(L: *mut lua_State, modname: *const libc::c_char, openf: lua_CFunction2, glb: c_int);

pub fn luaL_openlibs(L: *mut lua_State);

pub fn luaopen_base(L: *mut lua_State);
Expand Down