İşçi dosyasındaki bir işlevi çağıran ve bazı verileri ana iletiye geçiren Rust'tan bir web çalışanı oluşturmaya çalışıyorum.Emscripten hedefi ile Rust'tan web çalışanı oluşturma
main.rs
mod externs;
extern crate libc;
fn main() {
println!("starting worker");
let worker = externs::create_worker("./worker.js");
externs::call_worker(worker, "worker_fn", "", 0);
println!("worker called");
}
worker.rs
#![feature(link_args)]
#[link_args = "-s EXPORTED_FUNCTIONS=['_worker_fn'] -s BUILD_AS_WORKER=1"]
extern crate libc;
mod externs;
extern {}
fn main() {
println!("worker main");
}
#[no_mangle]
pub extern fn worker_fn() {
println!("hello from the other side!");
}
Ben işçi ve ana dosyaları derlemek, ben bile main.rs
ve gelen mesajı görmek mümkün değilim işçi dosyasında "işçi ana" mesajı. Ayrıca, tarayıcının worker.js
'a bir istek gönderdiğini de görebiliyorum, ancak ana iş parçacığının çalışan dosyasında worker_fn
'u aramadığı görülüyor. Sorunun ne olduğunu anlamıyorum
use std::ffi::CString;
use libc::*;
use std::str::FromStr;
/// Creating web worker
pub fn create_worker(url: &str) -> ffi::worker_handle {
let url = CString::new(url).unwrap();
let ptr = url.as_ptr();
unsafe { ffi::emscripten_create_worker(ptr) }
}
extern "C" fn do_something_handler(arg1: *mut c_char, arg2: c_int, arg3: *mut c_void) {
println!("worker done!");
}
/// Creating web worker
pub fn call_worker(worker: ffi::worker_handle, func_name: &str, data: &str, size: i32) {
let func_name = CString::new(func_name).unwrap();
let mut string = String::from_str(data).unwrap();
let bytes = string.into_bytes();
let mut cchar : Vec<c_char> = bytes.iter().map(|&w| w as c_char).collect();
let data_slice = cchar.as_mut_slice();
let mut state = 42;
let state_ptr: *mut c_void = &mut state as *mut _ as *mut c_void;
unsafe {
ffi::emscripten_call_worker(
worker,
func_name.as_ptr(),
data_slice.as_mut_ptr(),
size as c_int,
Some(do_something_handler),
state_ptr
)
};
}
// This is mostly standard Rust-C FFI stuff.
mod ffi {
use libc::*;
pub type worker_handle = c_int;
pub type em_worker_callback_func = Option<unsafe extern "C" fn(arg1: *mut c_char,
arg2: c_int,
arg3: *mut c_void)>;
extern "C" {
pub fn emscripten_run_script_int(x: *const c_char) -> c_int;
pub fn emscripten_create_worker(url: *const c_char) -> worker_handle;
pub fn emscripten_call_worker(
worker: worker_handle,
funcname: *const c_char,
data: *mut c_char,
size: c_int,
callback: em_worker_callback_func,
arg: *mut c_void
);
pub fn emscripten_worker_respond(data: *mut c_char, size: c_int);
pub fn emscripten_worker_respond_provisionally(data: *mut c_char, size: c_int);
}
}
:
Bu
externs
dosyasıdır. İşçi dosyasını ya da belki de
link_args
'u değiştirmeli miyim? ,
worker.rs
#![feature(link_args)]
#[link_args = "-s BUILD_AS_WORKER=1"]
#[macro_use]
extern crate stdweb;
fn main(){
stdweb::initialize();
js! {
this.addEventListener("message", (e) => {
console.log("The main thread said something", e.data);
})
}
stdweb::event_loop();
}
loader.js
var wasm_file = "worker.wasm"; // wasm file
var wjs_file = "worker.js"; // w.js file that links the wasm file
Module = {}
console.log("Loading webassembly version");
/// fetch wasm file and inject the js file
fetch(wasm_file)
.then(response => response.arrayBuffer())
.then(bytes => {
Module.wasmBinary = bytes;
console.log("wasm has loaded..");
console.log("attaching as script");
self.importScripts(wjs_file);
});
ve son olarak:
"worker.js" dosyasının neden gerekli olduğunu anlamama yardımcı olun. 'Loader.js'' Worker' içinde çalışırsa, neden sadece wasm dosyasını doğrudan yüklemiyor? Bunun yerine, "importScripts" ifadesini kullanarak wasm dosyasını yüklemek için "worker.js" komutunu kullanmaktadır. Neden bu ekstra dolaylı katman? –