【发布时间】:2018-05-12 13:45:07
【问题描述】:
我正在用 Rust 构建一个 Redis 模块。我找到了一些很好的例子,但是在处理应该接受可变参数的 C 函数的接口时我被卡住了。
Redis 模块 C SDK 有一个名为 RedisModule_Call 的函数,它接受一些特定的参数,然后是代表 Redis 命令的 n 参数。来自Redis Module SDK 文档(C 语言):
RedisModuleCallReply *reply;
reply = RedisModule_Call(ctx,"INCR","sc",argv[1],"10");
RedisModule_Call 的前三个参数是特定的,但其余的代表可能很容易有数百个参数的 Redis 命令。
在 Rust 中,我遵循 Redis-Cell 中的模式,这是一个在 Rust 中(成功)实现的 Redis 模块。该模块非常棒,但处理这个特定问题的方法非常有限。实际上,它以某种蛮力的方式最多接受三个参数:
pub fn call(&self, command: &str, args: &[&str]) -> Result<Reply, CellError> {
// ... code ...
let raw_reply = match args.len() {
1 => raw::call1::call(/* ... */),
2 => raw::call2::call(/* ... */),
// ...
这些call1 和call2 函数实际上只是处理不同参数长度的存根:
pub mod call2 {
use redis::raw;
pub fn call(
ctx: *mut raw::RedisModuleCtx,
cmdname: *const u8,
fmt: *const u8,
arg0: *mut raw::RedisModuleString,
arg1: *mut raw::RedisModuleString,
) -> *mut raw::RedisModuleCallReply {
unsafe { RedisModule_Call(ctx, cmdname, fmt, arg0, arg1) }
}
#[allow(improper_ctypes)]
extern "C" {
pub static RedisModule_Call: extern "C" fn(
ctx: *mut raw::RedisModuleCtx,
cmdname: *const u8,
fmt: *const u8,
arg0: *mut raw::RedisModuleString,
arg1: *mut raw::RedisModuleString,
) -> *mut raw::RedisModuleCallReply;
}
}
我需要能够传入n 参数,n 在运行时确定,因此这种硬编码方法不实用。我知道 Rust 对可变参数函数的支持有限,并且我一直在阅读有关 RFC 2137 的内容,但我不确定这是否适用。
我正在寻找一种将参数向量应用于RedisModule_Call 末尾的方法,或者类似于参数的扩展语法。我对 Rust 比较陌生,但我已经搜索和搜索了,我似乎找不到任何方法来解决 Rust 中的这种痒。
澄清一下-我可以将参数传递给RedisModule_Call(可变参数)没问题,但是我找不到将Rust中可变数量的参数传递给C函数的语法方法。我想要完成的是这样的:
impl Redis {
pub fn call(&self, command: &str, args: &[&str]) -> Result<Reply, CellError> {
/* ... */
unsafe { RedisModule_Call(ctx, cmdname, fmt, ...args) }
/* ... */
...args 是某种黑魔法,它允许 args 表示 1 个参数或 100,这相当于 RedisModule_Call(ctx, cmdname, fmt, args[0], args[1] /* ... and so on */)。
【问题讨论】:
-
“我需要能够传入n个参数,n在运行时确定,所以这种硬编码方法不实用。”,不清楚你在这里问什么,C标准不允许这样的事情。