【发布时间】:2020-01-01 13:43:07
【问题描述】:
我正在尝试创建一个通用接口,以便能够使用来自 python(https://github.com/ProjitB/Rust-Libraries-to-Python) 的 rust 库。现在,虽然我有一个工作版本,但我在传递数据的过程中创建了一个临时文件,我想避免这种情况。关于如何做到这一点的任何想法?
所以我要做的是在 rust 中编写一个接口函数,它调用了我想从 python 中使用的 rust 库函数。为了从 python 传递参数,我通过 pickle 将其写入临时文件,并通过 serde_pickle 读取 rust 端的 args。
我坚持的是,虽然我能够将字符串从 python 传递给 rust(例如,文件名本身现在作为字符串传递),但当我无法使用 pickle 序列化数据时.也许是因为空字节?
# Rust Function Interface Definitions
ffi = FFI()
ffi.cdef("""
typedef struct {int length; const char* response;} RetStruct;
RetStruct rust_post(const char*);
""")
LIB = ffi.dlopen("target/release/librequest_export.dylib")
def function_call(function, data):
inp_file = tempfile.NamedTemporaryFile()
with open(inp_file.name, 'wb') as handle:
pickle.dump(data, handle, protocol=pickle.HIGHEST_PROTOCOL)
val = function(to_string(inp_file.name))
obj = pickle.loads(read_pickle_bytes(val.response, val.length))
return obj['response']
def test_function_call():
data = {'url': 'https://postman-echo.com/post', 'data': {"hello": "world"}}
output = eval(function_call(LIB.rust_post, data))
print(type(output))
print(output)
print(output["args"])
test_function_call()
use reqwest;
use url::Url;
use std::os::raw::c_char;
use std::ffi::CStr;
use serde_json as json;
use serde_pickle as pickle;
use std::collections::BTreeMap;
use std::fs;
use std::fs::File;
use std::io::{Read};
use std::mem;
#[repr(C)]
pub struct RetStruct {
length: i64,
response: *mut u8
}
pub extern "C" fn rust_post(input_temp_file: *const c_char) -> RetStruct{
// File to read and write to
let input_filename = unsafe { CStr::from_ptr(input_temp_file).to_str().expect("Not a valid UTF-8 string") };
//Processing
let reader: Box<Read> = Box::new(File::open(input_filename).unwrap());
let decoded: json::Value = pickle::from_reader(reader).unwrap();
let mut map = BTreeMap::new();
//To Implement
let data = &decoded["data"];
let url = Url::parse(&decoded["url"].as_str().expect("Not a valid UTF-8 string")).unwrap();
let client = reqwest::Client::new();
let mut resp = client.post(url)
.json(&data)
.send().unwrap();
map.insert("response".to_string(), resp.text().unwrap());
//Processing
let mut serialized = serde_pickle::to_vec(&map, true).unwrap();
let x = serialized.len();
let p = serialized.as_mut_ptr();
mem::forget(serialized);
RetStruct{
length: x as i64,
response: p
}
}
代码显示了我当前如何在 python 和 rust 之间传递数据。如果我尝试以发送文件名的方式发送序列化的泡菜数据,我将无法恢复所有数据。
【问题讨论】:
标签: python rust python-cffi