2012-09-10 13 views
15

मेरे पास EMScripten के माध्यम से जावास्क्रिप्ट में परिवर्तित C++ कोड का एक टुकड़ा है। मैं परिवर्तित सी ++ कोड को जावास्क्रिप्ट कोड पर कॉल करने के लिए कॉल करना चाहता हूं जो इसे कॉल करता है।ईएमएसस्क्रिप्ट-जेनरेट कोड पर जेएस फ़ंक्शन पास करना

जावास्क्रिप्ट: की तरह कुछ

function callback(message) { 
    alert(message); 
} 

ccall("my_c_function", ..., callback); 

सी ++:

void my_c_function(whatever_type_t *callback) { 
    callback("Hello World!"); 
} 

यह संभव किसी भी तरह है?

उत्तर

13

मेरा मानना ​​है कि स्वीकृत उत्तर थोड़ा पुराना है।

कृपया this bullet point in the "Interacting with code" emscripten tutorial देखें।

उदा। सी:

void invoke_function_pointer(void(*f)(void)) { 
    (*f)(); 
} 

जे एस:

var pointer = Runtime.addFunction(function() { 
    console.log('I was called from C world!'); 
}); 
Module.ccall('invoke_function_pointer', 'number', ['number'], [pointer]); 
Runtime.removeFunction(pointer); 

इस तरह सी कोड है कि यह जे एस के लिए transpiled जाता है और किसी भी आवश्यक पुलों विशुद्ध रूप से जे एस से नियंत्रित किया जा सकता बारे में पता होना करने के लिए की जरूरत नहीं है ।

(संदेश संगीतकार काट दिया कोड; त्रुटियां हो सकती हैं)

+0

एक महत्वपूर्ण बात यह है कि फंक्शन पॉइंटर्स की संख्या जो एक साथ वैध हैं, निश्चित रूप से तय की जाती हैं और निर्दिष्ट 'emcc ... -s RESERVED_FUNCTION_POINTERS = 20 ... ' –

10

ईएमएसस्क्रिप्ट में अक्सर किया जाने वाला एक चीज़ सरल प्रकारों को मजबूत प्रकारों को मैप करना है।

जे एस:

function callback(message) { 
    alert(message); 
} 

var func_map = { 
    0: callback 
}; 

// C/C++ functions get a _ prefix added 
function _invoke_callback(callback_id, text_ptr) { 
    func_map[callback_id](Pointer_stringify(text_ptr)); 
} 

ccall("my_c_function", ..., 0); 

सी ++:

// In C/C++ you only need to declare the func signature and 
// make sure C is used to prevent name mangling 
extern "C" void invoke_callback(int callback_id, const char* text); 

void my_c_function(int callback_id) { 
    invoke_callback(callback_id, "Hello World!"); 
} 

और निश्चित रूप से, आप कुछ गोंद कोड जोड़ सकते हैं, तो यह बहुत सहज हो जाता है।

+3

+1 C++ नाम मैंगलिंग से बचने के लिए उल्लेख करने के लिए +1। – Eonil

+0

क्या आप इस संबंधित प्रश्न को देख सकते हैं: http://stackoverflow.com/questions/33673575/where-should-i-defined-emscripten-extern-functions-in-js?noredirect=1#comment55119884_33673575 –

1

मैं बहुत क्या सवाल में वर्णन किया गया है करने के लिए कुछ इसी तरह लिखने के लिए की जरूरत है।

C:

void call(void (*back)(char*)){ 
    back("Hello!"); 
} 

जे एस:

function back(text){ 
    alert(Pointer_stringify(text)); 
} 
var pointer = Runtime.addFunction(back); 
var call = Module.cwrap('call', 'void', ['pointer']); 
call(pointer); 
Runtime.removeFunction(pointer); 

ध्यान दें कि सूचक कॉलबैक को लौट Pointer_stringify साथ dereferenced हो गया है मेरे कोड इस तरह की तलाश में समाप्त हो गया।

आप गिटहब पर इस तरह example code पा सकते हैं।

+0

लिंक कोई अतिरिक्त जानकारी प्रदान करता है। –

0

यहाँ मैं क्या कई पदों से और Emscripten को देखकर इकट्ठे हुए हैं कोड बंडल:

C++ में:

#include <iostream> 
#include <functional> 

extern "C" { 
    void registerCallback(void(*back)(const char*)); 
    void triggerCallback(char* message); // for invoking it from JS, just for this example 
} 

// global 
std::function<void(const char*)> gCallback; 

void registerCallback(void(*back)(const char*)){ 
    gCallback = back; 
} 

void triggerCallback(char* message){ 
    if (gCallback) { 
    gCallback(message); 
    } else { 
    std::cerr << "Cannot pass '"<< message <<"' to undefined callback\n"; 
    } 
} 

एक महत्वपूर्ण बात है, जो अन्य पदों में याद आ रही थी, सी संकलित करने के लिए है ++ के साथ RESERVED_FUNCTION_POINTERS = ... झंडा, जैसे:

em++ -std=c++11 -s RESERVED_FUNCTION_POINTERS=20 source.cpp -s EXPORTED_FUNCTIONS="['_registerCallback','_triggerCallback']" -o try.html 

के बाद एक ब्राउज़र में लोड हो रहा है try.html, आप अपनी कंसोल में निम्नलिखित जे एस कोड निष्पादित कर सकते हैं:

// Register a callback function 
function callback(text){ alert("In JS: "+Pointer_stringify(text)); } 
var cb = Runtime.addFunction(callback); 
_registerCallback(cb); 

// Invoke it with some "C string" 
var jsStr = "XOXOXO"; 
var cStr = allocate(intArrayFromString(jsStr), 'i8', ALLOC_NORMAL) 
_triggerCallback(cStr); 

// Free Emscripten heap and release the function pointer 
_free(cStr); 
Runtime.removeFunction(cb); 

आप "जे एस के साथ एक चेतावनी देखना चाहिए: XOXOXO "।

2

आपकी आवश्यकता को प्राप्त करने का एक नया तरीका है जो embind के माध्यम से है।

सी ++ कोड के निम्नलिखित भाग पर विचार करें।

#include <emscripten/bind.h> 
using namespace emscripten; 

void cbTest(emscripten::val cb) 
{ 
    cb(); 
} 

EMSCRIPTEN_BINDINGS(my_module) { 
    function("cbTest", &cbTest); 
} 

cbTest सी ++ समारोह एक emscripten::val में ले जाता है। यह किसी भी तरह का एक वस्तु हो सकता है। हमारे लिए यह एक कार्य वस्तु है। इससे आपको इसके जे एस

से कॉल करेंगे
var cbFunc = function() { 
    console.log("Hi, this is a cb"); 
} 

Module.cbTest(cbFunc); 

पी.एस यह API निर्माणाधीन अभी भी है।

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