-
Notifications
You must be signed in to change notification settings - Fork 116
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
Suggestion: proc_macro for LuaUserDataMethods::add_method #288
Comments
That does look like it'd make lots of bindings much nicer! |
For reference, I wrote a macro for registering global constructor functions for my bindings which basically does the alternative proposal: macro_rules! decl_func_constructor {
($handle: ident: |$ctx: ident| $imp: block) => {
paste::paste! {
fn [<register_ $handle:snake _constructor>]<'lua>(lua: LuaContext<'lua>) -> Result<(), LuaError> {
let globals = lua.globals();
let constructor = lua.create_function(|$ctx: LuaContext, ()| {
$imp
})?;
globals.set(stringify!($handle), constructor)?;
Ok(())
}
}
};
($handle: ident: |$ctx: ident, $($name: ident: $value: ident $( < $($gen: tt),* > )?),*| $imp: block) => {
paste::paste! {
fn [<register_ $handle:snake _constructor>]<'lua>(lua: LuaContext<'lua>) -> Result<(), LuaError> {
let globals = lua.globals();
let constructor = lua.create_function(|$ctx: LuaContext, args: LuaMultiValue| {
let mut args = args.into_iter();
$(
let $name: LuaValue = args.next().ok_or_else(|| LuaError::RuntimeError(
format!("missing '{}' argument in {} constructor; expected a value convertible to {}", stringify!($name), stringify!($handle), stringify!($value))
))?;
let $name: $value$(<$($gen),*>)? = FromLuaMulti::from_lua_multi(LuaMultiValue::from_vec(vec![$name]), $ctx, &mut 0).map_err(|inner| LuaError::CallbackError {
traceback: format!("while converting '{}' argument value", stringify!($name)),
cause: std::sync::Arc::new(inner),
})?;
)*
$imp
})?;
globals.set(stringify!($handle), constructor)?;
Ok(())
}
}
};
($handle: ident: |$ctx: ident, $multi: ident| $imp: block) => {
paste::paste! {
fn [<register_ $handle:snake _constructor>]<'lua>(lua: LuaContext<'lua>) -> Result<(), LuaError> {
let globals = lua.globals();
let constructor = lua.create_function(|$ctx: LuaContext, $multi: LuaMultiValue| {
$imp
})?;
globals.set(stringify!($handle), constructor)?;
Ok(())
}
}
};
} would require some minor tweaking to wrap This would probably have to be tuned to allow The issue with that implementation is that it doesn't handle complex types well (e.g. |
FWIW in one of my projects, I use a (declarative) macro which looks like: wrap_lua!(RServer impl () {
"add_redirect" => server_redirect(mut),
"add_literal" => server_literal(mut),
"add_part" => server_part(mut),
"shutdown" => server_shutdown(mut)
}); where the I also support traits: wrap_trait!(MyTrait {
"meth" => mytrait_meth(const),
"othermeth" => mytrait_othermeth(const)
});
wrap_type1(Type1 impl (MyTrait) {
"type1_meth" => type1_meth(const)
}); From Lua a |
It would be really nice if
rlua
provided a macro that allowed declaring methods viaadd_method
andadd_method_mut
onUserData
in a simpler way.Something like:
This is quite involved to implement. Note that
_self
handling requires modification of the inner code block, butsyn
has avisit-mut
feature for precisely this functionality.Benefits
Alternative proposal
A normal macro that wraps individual
add_method
calls would still allow generating more specific error messages while avoiding separation of argument names and types in callback signature.The text was updated successfully, but these errors were encountered: