2017-07-29 7 views
6

से वेबसाइस्प्लोर में एक सी स्टाइल फ़ंक्शन पॉइंटर को कॉल करना क्या WebAssembly मॉड्यूल के अंदर रहने वाले फ़ंक्शन पॉइंटर्स तक पहुंच प्राप्त करने का कोई तरीका है?जावास्क्रिप्ट

उदाहरण के लिए

, यह देखते हुए "मॉड्यूल" WebAssembly को संकलित निम्नलिखित:

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

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

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

जावास्क्रिप्ट में do_callback के एक कार्यान्वयन के लिए एक मध्यस्थ सी समारोह निर्यात पर भरोसा करने की वास्तविक समारोह कॉल करने के लिए बिना कॉलबैक आह्वान कर सकते हैं ?

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

मध्यस्थ कार्य निर्यात द्वारा, मेरा मतलब है कि मैं सार्वजनिक दृश्यता के साथ एक आंतरिक कार्य जोड़ सकता हूं।

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

फिर जावास्क्रिप्ट set_callback समारोह प्रतिनिधि do_callback समारोह के माध्यम से समारोह सूचक कॉल कर सकते हैं।

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

लेकिन, यह है कि स्पष्ट अविवेक के माध्यम से जाने के बिना यह करने के लिए प्राथमिकता दी जाती है, यह संभव है, कार्य तालिकाओं शायद के साथ?

उत्तर

0

आप जावास्क्रिप्ट से फ़ंक्शन पॉइंटर्स का आह्वान कर सकते हैं।

फ़ंक्शन पॉइंटर्स एक तालिका में संग्रहीत हैं। जब जावास्क्रिप्ट को फ़ंक्शन पॉइंटर पास किया जाता है तो आपको उस फ़ंक्शन पॉइंटर के लिए तालिका में पूर्णांक अनुक्रमणिका प्राप्त होती है। उस सूचकांक को Table.prototype.get() पर पास करें और आप फ़ंक्शन को कॉल कर सकते हैं।

... 

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

... 

आप टेबल्स धारा के तहत इस MDN पृष्ठ पर इस बारे में और अधिक पढ़ सकते हैं: https://developer.mozilla.org/en-US/docs/WebAssembly/Using_the_JavaScript_API#Tables

संपादित करें: यहाँ कम से कम उदाहरण मैं इस परीक्षण के लिए किया है।

पहली फ़ाइल 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); 
} 

साथ संकलित और यहाँ 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

यह पहले से ही के रूप में कार्य तालिकाओं का वर्णन मूल रूप से के रूप में लिखा है "यह एक समारोह सूचक तालिका, इस्तेमाल होता है की कोशिश की है यह सी स्टाइल फ़ंक्शन पॉइंटर्स के लिए "लेकिन मॉड्यूल के आयात डिस्क्रिप्टर को टेबल पास करने का कोई प्रभाव नहीं पड़ता है, और तालिका खाली हो जाती है? –

+0

@ कैस्परबेयर मैंने अपनी पोस्ट को उस उदाहरण के उदाहरण को संपादित करने के लिए संपादित किया है जिसका उपयोग मैंने परीक्षण करने के लिए किया था। – Ghillie

+0

ईएमएसस्क्रिप्टन के बिना टेबल और मेमोरी के लिए आयात उत्पन्न करने के लिए मुझे क्लैंग कैसे मिलेगी? इसे लिंकर स्तर पर करें? उदाहरण के साथ एक "खाली" मॉड्यूल के साथ wasm-link? –

संबंधित मुद्दे