2017-07-21 26 views
10

İşç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:

cevap

4

böyle stdweb sandık (teşekkürler ivanceras) kullanarak sorunu giderilmiştir HTML dosyası:

<script> 
    var worker = new Worker("loader.js"); 
    setTimeout(function() { 
     worker.postMessage({"cmd":"doSomething"}); 
    }, 1000); 
</script> 

Eğer Pas dosyasını oluştururken --target=wasm32-unknown-emscripten bayrak eklemek unutmayın

.

+0

"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? –