2016-03-04 274 views
0

我有一個關於Emscripten的小問題。 如何從JavaScript異步調用C++回調?使用Emscripten異步調用C++函數

這是我的JS代碼:

<script type="text/javascript"> 
    function sendRequest(callback) { 
     setTimeout(function(){ 
     callback["sayHi"](); 
     }, 100); 
    } 
    </script> 

這是我的C++代碼:

#include <emscripten/emscripten.h> 
#include <emscripten/bind.h> 

using namespace emscripten; 
class MyClass { 
    public: 
    void sayHi() { 
     printf("Hello! \n"); 
    }; 
}; 
EMSCRIPTEN_BINDINGS(MyClass) 
{ 
    class_<MyClass>("MyClass") 
     .function("sayHi", &MyClass::sayHi); 
} 

int main() { 
    val window = val::global("window"); 
    auto myObj = MyClass(); 
    window.call<void>("sendRequest", myObj); 
    return 0; 
} 

當我執行這個代碼,它失敗,出現錯誤:

Uncaught BindingError: Cannot pass deleted object as a pointer of type MyClass* 

我用EMCC 1.35.22並用此命令進行編譯:

~/app/emsdk_portable/emscripten/tag-1.35.22/emcc main.cpp --bind -o out.js 
+0

如果代碼是不是異步是否行得通? – Louis

+0

是的,如果我打電話回叫[「sayHi」](); setTimeout之前,然後它的作品。 – AndriiHeonia

回答

1

出於某種原因,當您通過堆棧從上面的行清時叫

window.call<void>("sendRequest", myObj); 

,Emscripten/embind刪除myObj(你可以看到這一點,如果你添加一個析構函數MyClass的)。

的第二個問題是,即使Emscripten/embind沒有這樣做,當你做

auto myObj = MyClass(); 

mainmyObj是在棧上創建的,所以它會在年底被刪除main,它位於異步回調之前。

圍繞這兩個方法的一種方法是在堆上創建對象,將其作爲原始指針傳遞給Javascript,並將函數指針傳遞給靜態回調函數。您可以使用EM_ASM_ARGS從C++中調出,然後使用dynCall_*函數從Javascript中的函數指針調用。

例如,C++會像

void callback(MyClass *myObj) 
{ 
    myObj->sayHi(); 
} 

MyClass *myObj; 

int main() { 
    myObj = new MyClass(); 

    EM_ASM_ARGS({ 
    sendRequest($0, $1); 
    }, &callback, myObj); 

    // myObj is still in memory 
    // be sure to delete it 
    return 0; 
} 

和JavaScript

Module = { 
    noExitRuntime: true 
}; 

function sendRequest(callback, myObj) { 
    setTimeout(function() { 
    Module.dynCall_vi(callback, myObj); 
    }, 1000); 
} 
+0

嗨米哈爾,謝謝你的回答!但在真實世界的應用程序中,我的「sendRequest」不是全局函數。我可以以某種方式在EM_ASM_ARGS塊內調用JS對象的方法(emscripten :: val的方法)嗎?類似[this](https://github.com/AndriiHeonia/async-emcc/blob/84cfd6d0d6368616953ea7903daf9870893214e4/main.cpp#L41)? – AndriiHeonia

+0

@AndriiHeonia從C++調用非全局JavaScript函數至少有一種方法。我不確定它是否適用於您的案例,因此我懷疑可能會發布具體問題的另一個問題,而不是嘗試按評論排序。 –

+0

我創建了新的問題:http://stackoverflow.com/questions/35846606/call-method-of-the-emscriptenval-inside-em-asm-args-block我會很樂意閱讀你的想法:)謝謝提前。 – AndriiHeonia