RustからWebワーカーを作成しようとしています。ワーカーファイルで関数を呼び出し、メインスレッドにデータを渡しています。RustからEmscriptenターゲットを使用してWebワーカーを作成する
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!");
}
私は労働者と主なファイルをコンパイル、私もmain.rs
からのメッセージを見ることができますよワーカーファイル内の「ワーカーメイン」メッセージ。私はまた、ブラウザがworker.js
に要求を送信するのを見ることができますが、メインスレッドがワーカーファイル内のworker_fn
を呼び出さないようです。
これはexterns
ファイルです:私は問題が何であるかを理解していない
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);
}
}
。私はどういうわけかワーカーファイルを変更するか、あるいはlink_args
を変更する必要がありますか? 、
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);
});
し、最終的に:
「worker.js」が必要な理由を理解してください。 'loader.js'が' Worker'内で実行されると、wasmファイルを直接読み込むのはなぜですか?代わりに 'importScripts'を使用して、wasmファイルをロードするはずの' worker.js'に渡します。なぜこの間接の層が増えるのでしょうか? –