2016-03-04 273 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