我正在尝试创建一个通用接口(interface),以便能够使用来自 python ( https://github.com/ProjitB/Rust-Libraries-to-Python ) 的 Rust 库。现在,虽然我有一个工作版本,但我正在传递数据的过程中创建一个临时文件,我想避免这种情况。关于如何执行此操作的任何想法?
所以我所做的是用 rust 编写一个接口(interface)函数,它调用了我想从 python 中使用的 rust 库函数。为了从 python 传递参数,我通过 pickle 将其写入临时文件,并通过 serde_pickle 读取使用rust 端的参数。
我坚持的是,虽然我能够将字符串从 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 之间传递数据。如果我尝试以发送文件名的方式发送序列化的 pickle 数据,我将无法恢复所有数据。
最佳答案
序列化为 json 总是一个好主意。
print({'url': 'https://postman-echo.com/post', 'data': {"hello": "world"}})
是 {'url': 'https://postman-echo.com/post', 'data': {'hello': 'world'}}
import json
print(json.dumps({'url': 'https://postman-echo.com/post', 'data': {"hello": "world"}}))
是 {"url": "https://postman-echo.com/post", "data": {"hello": "world"}}
引号很重要,注意 '
和 "
的区别。
关于python - 通过 pickle(或其他)将 json 数据从 python 传递到 rust,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57690545/