Hi guys
I'm trying to use jsonrpc library from parity tech. I'm basing my work on this example. Here's the code with the problem:
use jsonrpc_http_server::jsonrpc_core::*;
use jsonrpc_http_server::{AccessControlAllowOrigin, DomainsValidation, RestApi, ServerBuilder};
struct DataReader<'a> {
datadir: &'a std::path::Path,
}
impl<'a> DataReader<'a> {
fn new(data_dir: &'a std::path::Path) -> Self {
DataReader {
datadir: data_dir,
}
}
}
fn initiate(datadir: &std::path::Path) {
let mut io = IoHandler::default();
let datadir_rc = std::sync::Arc::new(datadir.to_owned());
io.add_method("say_hello", |_params: Params| // error here
{
let x = DataReader::new(datadir_rc.as_path()); // error here
Ok(Value::String("hello".to_string()))
});
let server = ServerBuilder::new(io)
.threads(3)
.rest_api(RestApi::Unsecure)
.cors(DomainsValidation::AllowOnly(vec![AccessControlAllowOrigin::Any]))
.start_http(&"127.0.0.1:3030".parse().unwrap())
.expect("Unable to start RPC server");
}
fn main() {
let p = std::path::PathBuf::new(); // assume we get this from command-line arguments
initiate(p.as_path());
}
Unfortunately, I can't put this on playground, because that library is not on playground. For this test, however, this is my Cargo.toml
.
[package]
name = "FnTest"
version = "0.1.0"
authors = [""]
edition = "2018"
[dependencies]
jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc" }
Now the problem is that the datadir must be posted in every instance of the closure in the async threads (it's a multithreaded program, so multiple copies have to go around. For that (and since I'm originally a C++ programmer), I'm trying to use the C++ way. I tried to pass that path as a shared pointer, so Arc
in rust. However, the problem is that rust keeps thinking that the closure may outlive the variable. It's not true though!
Now in C++, you'd guarantee that a shared pointer will outlive the closure by passing the shared pointer as a captured variable, like this (imitating add_method
from above):
auto datadir = std::make_shared<const std::string>("/home/user/mypath");
io.add_method("get_data", [datadir](const auto& params) {
// now datadir is guaranteed to live in all threads
});
How do we do the same in rust?
If what I'm doing here is wrong, what's the right way?
Thanks in advance!
EDIT: I wanna mention that the closure in that method implements the trait Fn
.