-
I'm porting a large C codebase, and need to provide a C API for static VEC2_METATABLE: &[u8; 5] = b"vec2\0";
#[unsafe(no_mangle)]
pub unsafe extern "C" fn lua_tovector( L: *mut mlua::lua_State, ind: c_int ) -> *mut Vec2 {
unsafe {
ffi::lua_touserdata( L, ind ) as *mut Vec2
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn luaL_checkvector( L: *mut mlua::lua_State, ind: c_int ) -> *mut Vec2 {
unsafe {
match lua_isvector( L, ind ) {
0 => {
ffi::luaL_typerror( L, ind, VEC2_METATABLE.as_ptr() as *const c_char );
std::ptr::null_mut()
},
_ => lua_tovector( L, ind ),
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn lua_pushvector( L: *mut mlua::lua_State, vec: Vec2 ) -> *mut Vec2 {
let size = std::mem::size_of::<Vec2>();
unsafe {
let v: *mut Vec2 = ffi::lua_newuserdata( L, size ) as *mut Vec2;
std::ptr::copy_nonoverlapping( &vec as *const Vec2, v, size );
ffi::luaL_getmetatable( L, VEC2_METATABLE.as_ptr() as *const c_char );
ffi::lua_setmetatable( L, -2 );
v
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn lua_isvector( L: *mut mlua::lua_State, ind: c_int ) -> c_int {
unsafe {
if ffi::lua_getmetatable( L, ind ) == 0 {
return 0;
}
ffi::lua_getfield( L, ffi::LUA_REGISTRYINDEX, VEC2_METATABLE.as_ptr() as *const c_char );
let ret = match ffi::lua_rawequal( L, -1, -2 ) { /* Check metatable. */
0 => 0,
_ => 1,
};
ffi::lua_pop( L, 2 ); /* remove both metatables */
ret
}
} I'm registering the module with: globals.set("vec2", lua.create_proxy::<Vec2>()?)?; It seems like the mlua userdata is dealing with this differently from the C API so it fails to detect the userdata as the correct type. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
mlua by-design support only userdata that were made using mlua (high level) api, to ensure data types safety. Probably the easiest way would be making
|
Beta Was this translation helpful? Give feedback.
Check my example, it works: