2017-07-29 58 views
6

WebAssembly modülünde yaşayan işlev işaretçilerine erişim elde etmek için herhangi bir yol var mı? Verilen örnek içinBir WebAssembly uygulamasında bir C stili işlev işaretçisini JavaScript'ten çağırma

, WebAssembly için derlenmiş "modülü" Aşağıdaki:

extern void set_callback(void (*callback)(void *arg), void *arg); 

static void callback(void *arg) 
{ 
    /* ... */ 
} 

int main() { 
    set_callback(&callback, 0); 
    return 0; 
} 

JavaScript do_callback bir uygulama fiili işlev çağrısını yapmak için bir aracı C işlevi ihracat güvenmek zorunda kalmadan geri arama çağırmak Can ?

var instance = new WebAssembly.Instance(module, { 
    memory: /* ... */ 
    env: { 
    set_callback: function set_callback(callbackptr, argptr) { 
     // We only got the pointer, is there any 
    }, 
    }, 
}); 

Arabirim işlevi dışa aktarma yoluyla, genel görünürlüğe sahip bir dahili işlev ekleyebileceğimi kastediyorum.

do_callback(void (*callback)(void *arg), void *arg) 
{ 
    callback(); 
} 

Sonra JavaScript set_callback fonksiyonu temsilci do_callback fonksiyonu aracılığıyla işlev işaretçisi çağırabilir.

function set_callback(callbackptr, argptr) { 
    instance.exports.do_callback(callbackptr, argptr); 
} 

Ancak, bu açık dolaylama yoluyla gitmek zorunda kalmadan bunu yapmak için tercih edilir belki fonksiyon tablolarla, mümkün mü?

cevap

0

İşlev göstergelerini Javascript'ten çağırabilirsiniz.

İşlev işaretçileri Tabloda saklanır. Bir işlev işaretçisi Javascript'e iletildiğinde, tamsayı dizinini bu işlev işaretçisi için tabloya alıyorsunuz. Bu endeksi Table.prototype.get()'a iletin ve işlevi çağırabilirsiniz.

... 

set_callback: function set_callback(callbackptr, argptr) { 
    tbl.get(callbackptr)(argptr); 
}, 

... 

Sen Tablolar bölümünde bu MDN sayfasından bu konuda daha fazla bilgi edinebilirsiniz: https://developer.mozilla.org/en-US/docs/WebAssembly/Using_the_JavaScript_API#Tables

Edit: İşte bu sınamak için kullanılan minimal bir örnektir.

ilk dosya fptr.cemcc fptr.c -Os -s WASM=1 -s SIDE_MODULE=1 -o fptr.wasm

typedef int (*fptr_type)(void); 

extern void pass_fptr_to_js(fptr_type fptr); 

static int callback_0(void) 
{ 
    return 26; 
} 

static int callback_1(void) 
{ 
    return 42; 
} 

void run_test() 
{ 
    pass_fptr_to_js(callback_0); 
    pass_fptr_to_js(callback_1); 
} 

ile derlenmiş Ve burada fptr.html

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="UTF-8"> 
    <title>WebAssembly Experiment</title> 
</head> 
<body> 
    <h3>Check the console.</h3> 
    <script type="text/javascript"> 
     fetch('fptr.wasm').then(function(response) { 
      response.arrayBuffer().then(function(buffer) { 
       WebAssembly.compile(buffer).then(function(module) { 
        var imports = {}; 

        imports.env = {}; 

        imports.env.memoryBase = 0; 
        imports.env.memory = new WebAssembly.Memory({ initial: 256 }); 
        imports.env.tableBase = 0; 
        imports.env.table = new WebAssembly.Table({ initial: 4, element: 'anyfunc' }); 

        imports.env["abort"] = function() { 
         console.error("ABORT"); 
        }; 

        imports.env["_pass_fptr_to_js"] = function(fptr) { 
         console.log("table index: " + fptr + ", return value: " + imports.env.table.get(fptr)()); 
        }; 

        WebAssembly.instantiate(module, imports).then(function(instance) { 
         instance.exports["__post_instantiate"](); 
         instance.exports["_run_test"](); 
        }); 
       }); 
      }); 
     }); 
    </script> 
</body> 
</html> 
+0

bu fonksiyon tabloları açıklama temelde olarak okur olarak zaten "bu bir işlev işaretçisi tablosu, kullanımıdır çalıştı mesafesindedir C stili işlev işaretçileri için "ancak bir modülün içe aktarım tanımlayıcısına giden tabloların gözlenebilir bir etkisi yoktur ve tablo boş bırakılır? –

+0

@CasperBeyer Bu yazıyı test etmek için kullandığım çalışma örneğini içerecek şekilde yayınımı düzenledim. – Ghillie

+0

Emscripten olmadan tablo ve bellek için ithalat üretmek için nasıl clang alabilirim? Linker seviyesinde mi? ör., ithalatı içeren bir "boş" modül ile wasm-link? –