Hi again
Sorry for the title, but it is the most precise I was able to find.
I found myself tricked in a problem quite interesting and I would like your help.
I have an external "C" library that accept a callback.
Since I (should be) am writing an abstraction over this library I want to write a safer and more ergonomic interface.
The overall goal is to have a wrapper where I can pass rusty parameters, make some magic with these parameters inside the body of the wrapper and transforming them in something more C-like, and finally invoke the extern C function.
The function I am invoking is this one:
extern "C" {
#[link_name = "RedisModule_CreateCommand"]
pub static mut RedisModule_CreateCommand:
::std::option::Option<unsafe extern "C" fn(
ctx: *mut RedisModuleCtx,
name: *const ::std::os::raw::c_char,
cmdfunc: RedisModuleCmdFunc,
strflags: *const ::std::os::raw::c_char,
firstkey: ::std::os::raw::c_int,
lastkey: ::std::os::raw::c_int,
keystep: ::std::os::raw::c_int)
-> ::std::os::raw::c_int>;
}
where
pub type RedisModuleCmdFunc =
::std::option::Option<unsafe extern "C" fn(
ctx: *mut RedisModuleCtx,
argv: *mut *mut RedisModuleString,
argc: ::std::os::raw::c_int)
-> ::std::os::raw::c_int>;
Finally the function I am trying to implement looks like this:
type RedisModuleCmdFuncSafe = Fn(Context, Vec<String>) -> i32;
fn CreateCommand<F>(ctx: Context,
name: String,
f: &F,
flags: String,
first_key: i32,
last_key: i32,
key_step: i32)
-> i32
where F: Fn(Context, Vec<String>) -> i32
{
let c_name = CString::new(name).unwrap();
let ptr_name = c_name.as_ptr();
let c_flags = CString::new(flags).unwrap();
let ptr_flags = c_flags.as_ptr();
let function = |ctx: *mut ffi::RedisModuleCtx,
argv: *mut *mut ffi::RedisModuleString,
argc: i32|
-> i32 {
let context = Context { ctx: ctx };
let argvector = parse_args(argv, argc).unwrap();
f(context, argvector)
};
let option_function = Some(function);
unsafe {
ffi::RedisModule_CreateCommand.unwrap()(ctx.ctx,
ptr_name,
option_function,
ptr_flags,
first_key,
last_key,
key_step)
}
}
Clearly this doesn't work since I am using a closure instead of a function and, however if I use a closure f
should be somewhere accessible after the completion of the function.
I believe I kinda get why it is not working, but I am not really able to see a solution myself.
Could you guys help?