从JavaScript异步调用C ++函数使用Emscripten [英] Call C++ function from JavaScript asynchronously using Emscripten
问题描述
我有一个关于Emscripten的小问题。
我如何从JavaScript异步调用C ++回调?
这是我的JS代码:
< script type =text / javascript>
function sendRequest(callback){
setTimeout(function(){
callback [sayHi]();
},100)
}
< / script>
这是我的C ++代码:
#include< emscripten / emscripten.h>
#include< emscripten / bind.h>
使用命名空间emscripten;
class MyClass {
public:
void sayHi(){
printf(Hello!\\\
);
};
};
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;
}
当我执行此代码时,会失败并显示错误:
未捕获的BindingError:无法将删除的对象作为MyClass类型的指针传递
我使用emcc 1.35.22并使用以下命令编译:
〜/ app / emsdk_portable / emscripten / tag-1.35.22 / emcc main.cpp --bind -o out.js
由于某种原因,当您调用
window.call< void& (sendRequest,myObj);
在堆栈从上面的行中清除时,Emscripten / embind删除 myObj
(你可以看到这个,如果你添加一个析构函数到MyClass)。
第二个问题是,即使Emscripten / embind didn' t做这个,当你做
auto myObj = MyClass
在 main
, myObj
在堆栈上创建,因此它将在异步回调之前的 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仍在内存中
//一定要删除它
return 0;
}
和Javascript
Module = {
noExitRuntime:true
};
function sendRequest(callback,myObj){
setTimeout(function(){
Module.dynCall_vi(callback,myObj);
},1000)
}
I have a small question about Emscripten. How can I call C++ callback asynchronously from JavaScript?
This is my JS code:
<script type="text/javascript">
function sendRequest(callback) {
setTimeout(function(){
callback["sayHi"]();
}, 100);
}
</script>
This is my C++ code:
#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;
}
When I execute this code it fails with error:
Uncaught BindingError: Cannot pass deleted object as a pointer of type MyClass*
I use emcc 1.35.22 and compile it with this command:
~/app/emsdk_portable/emscripten/tag-1.35.22/emcc main.cpp --bind -o out.js
For some reason, when you call
window.call<void>("sendRequest", myObj);
by the time the stack has cleared from the above line, Emscripten/embind deletes myObj
(You can see this if you add a destructor to MyClass).
A secondary issue is that even if Emscripten/embind didn't do this, when you do
auto myObj = MyClass();
in main
, myObj
is created on the stack, and so it would be deleted at the end of main
, which is before the asynchronous callback.
A way around both of these is to create the object on the heap, pass it to Javascript as a raw pointer, along with a function pointer to a static callback. You can use EM_ASM_ARGS
to call out from C++, and then use a dynCall_*
function to call from the function pointer from Javascript.
For example, the C++ would be like
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;
}
and the Javascript
Module = {
noExitRuntime: true
};
function sendRequest(callback, myObj) {
setTimeout(function() {
Module.dynCall_vi(callback, myObj);
}, 1000);
}
这篇关于从JavaScript异步调用C ++函数使用Emscripten的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!