标签: emscripten

如何在 Web Worker 中使用 emscripted .js 库

我已将程序编译为单个program.js文件,并在工作程序中调用:

importScripts('program.js');
Module.callMain();
Run Code Online (Sandbox Code Playgroud)

然而,尽管callMain正在执行,但在该函数调用的堆栈中我收到了错误Undefined is not a function

我的预感是我还没有阅读一些必要的emscripten文档、wiki 或源代码。

我知道的:

  • emscripten具有与工作程序一起使用的绑定,但仅当主线程上有 emscripted 进程才能使用这些绑定时(请参阅emscripten.h
  • 为了将任务(在主线程上运行的库内)编译给工作人员,需要在编译时为该任务emcc传递特殊选项(请参阅settings.js

我的猜测是:

  • 我可能需要传递一些标志来让 emcc 知道不要在不存在的对象上调用函数,例如window
  • /dev/tty在查看了与 by 链接的 的实现/dev/stdin以及 的实现之后/dev/stdout,我相信可能会有输出到console,我不认为工作人员支持该输出

我要问的是:

  • 如何在工作人员中使用我的库(单个 js 文件)?
    • 我的库从一个文件加载其他文件program.data(如果这有影响的话)

提前致谢。如果我可以添加任何详细信息,请告诉我。


注意:顶部的代码经过简化 - 它似乎不是语法错误。

更新:

  • stacktrace( Error.stack) 仅告诉我错误发生在Module.callMain. 它没有告诉我任何有关可能导致该问题的导入脚本的信息。:(

javascript web-worker emscripten

5
推荐指数
1
解决办法
1913
查看次数

在一个简单的(?)项目中使用 emscripten 和 CMake

所以我有一个相当简单的 C++ 程序,它使用CGAL并使用 CMake 构建。我可以在没有 emscripten 的情况下成功构建并运行它:

cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -G "Unix Makefiles" .
[output looks good]
make
[command works]
Run Code Online (Sandbox Code Playgroud)

一切都很好,我可以运行输出,但是当我尝试像这样使用 Emscripten 时(这在过去对我有用):

cmake -DCMAKE_TOOLCHAIN_FILE=/home/brenden/emsdk_portable/emscripten/master/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -G "Unix Makefiles" .
[output looks good]
make
main.cpp:2:10: fatal error: 'CGAL/Triangulation_3.h' file not found
#include <CGAL/Triangulation_3.h>
         ^
1 error generated.
ERROR    root: compiler frontend failed to generate LLVM bitcode, halting
make[2]: *** [CMakeFiles/cgal_test.dir/main.cpp.o] Error 1
make[1]: *** [CMakeFiles/cgal_test.dir/all] Error 2
make: *** [all] Error 2
Run Code Online (Sandbox Code Playgroud)

这显然是行不通的。

我的 CMakeLists.txt 如下所示:

cmake_minimum_required(VERSION …
Run Code Online (Sandbox Code Playgroud)

c++ cmake cgal emscripten

5
推荐指数
1
解决办法
9510
查看次数

如何将canvas imageData传递给emscripten c++程序而不复制它?

我有画布的图像数据:

myImage = ctx.getImageData(0, 0, 640, 480);
Run Code Online (Sandbox Code Playgroud)

我发现,我可以创建新的Uint8Array并用于set()复制图像数据。这是工作示例:

var numBytes = width * height * 4;
var ptr= Module._malloc(numBytes);
var heapBytes= new Uint8Array(Module.HEAPU8.buffer, ptr, numBytes);
heapBytes.set(new Uint8Array(myImage.data));
_processImage(heapBytes.byteOffset, width, height);
myImage.data.set(heapBytes);
Run Code Online (Sandbox Code Playgroud)

但是,不幸的是,每个.set()操作都比处理图像慢得多,并且上面的代码比 JS 实现慢!

所以,我想处理图像而不复制它。我可以通过这种方式成功地将数据直接读取和写入到堆中:

Module.HEAPU8.set(myImage.data, myImage.data.byteOffset);
_processImage(myImage.data.byteOffset, width, height);
myImage.data.set(new Uint8ClampedArray(Module.HEAPU8.buffer , myImage.data.byteOffset , numBytes));
Run Code Online (Sandbox Code Playgroud)

它更快,但第一个.set()执行仍然需要 17 毫秒。

C++函数原型为:

extern "C" {

    int processImage(unsigned char *buffer, int width, int height)
    {
    }

}
Run Code Online (Sandbox Code Playgroud)

有没有办法将数组传递给C++而不使用set()?只是告诉c++数据在内存中的位置,并允许修改它?

javascript c++ canvas emscripten asm.js

5
推荐指数
1
解决办法
2015
查看次数

嵌入传递 lambda 函数作为回调参数

我想创建一个函数来计算一些东西。完成后,它会调用回调函数。

void calculate(int param1, ..., std::function<void(void)> callback) {
    //code...
    callback();
}
Run Code Online (Sandbox Code Playgroud)

函数的绑定是使用以下命令创建的Embind

EMSCRIPTEN_BINDINGS(my_module) {
    function("calculate", &calculate);
}
Run Code Online (Sandbox Code Playgroud)

但如果我尝试打电话,Module.calculate(0, ..., function(){/*...*/})我会收到此错误:

UnboundTypeError: Cannot call calculate due to unbound types: NSt3__18functionIFvvEEE
Run Code Online (Sandbox Code Playgroud)

javascript c++ lambda emscripten

5
推荐指数
1
解决办法
2468
查看次数

是否可以像现在一样轻松编译 Emscripten,但没有控制台和 emscripten 徽标?

当使用 emscripten 不带任何参数编译 C++ 时,除了 webgl 画布之外,它还会生成一个带有控制台和 emscripten 徽标的 html 文件。

是否可以禁用 logo\console 并让它为填充 webgl 画布的空白网页生成 html\js ?

c++ frontend compilation emscripten

5
推荐指数
1
解决办法
1433
查看次数

具有原始数据指针和 emscripten 的对象

重新表述一下问题:

当我先验不知道数组的长度时,我应该如何将一个从 C/C++ API 返回一个以数组作为成员变量的对象的函数绑定到 javascript?


我有一个带有原始数据类型指针的结构

struct Person
{
    const char* name;
    int age;
    Person()
    {}
};
Run Code Online (Sandbox Code Playgroud)

我有一个函数应该返回这个结构的对象

Person getPerson()
{
    Person p = Person();
    p.name = "Philipp";
    p.age = 77;
    return p;
}
Run Code Online (Sandbox Code Playgroud)

以及以下约束:

EMSCRIPTEN_BINDINGS() {
    value_object<Person>("Person")
        .field("age", &Person::age)
        .field("name", &Person::name)
        ;

    function("getPerson", &getPerson);
}
Run Code Online (Sandbox Code Playgroud)

这不起作用,编译器还告诉我,static_assert failed "Implicitly binding raw pointers is illegal. Specify allow_raw_pointer<arg<?>>" 我试图理解API 文档,但无法使其工作。例如,我尝试将allow_raw_pointer()(及其变体)添加到 of.fieldname

c++ pointers emscripten

5
推荐指数
1
解决办法
2183
查看次数

从 WebAssembly .wasm 模块获取 JavaScript 导入对象条目

我想了解 Rust 程序在编译为 wasm 文件时实际导出的内容,以便我可以importObject为实例化函数提供有效的值:

WebAssembly.instantiate(bufferSource, importObject);
Run Code Online (Sandbox Code Playgroud)

据我了解,执行此操作的唯一方法是导出已编译代码的类似 s 语法的文件。我无法在他们的文档中或通过网络搜索找到如何执行此操作。

rust emscripten webassembly

5
推荐指数
1
解决办法
1886
查看次数

GHCJS 中 ccall 导入 emscripten 导出

我正在尝试使用 ghcjs 将 haskell 库minisat移植到 JavaScript,以便集成到更大的 haskell-ghcjs 项目中。

minisat 包含几个来自 ac 库的 ffi 导入。我已经设法使用 emscripten 将 c 库编译为 javascript,并导出 minisat 所需的函数。到目前为止,一切都很好。

然而,有一些导入看起来像这样:

foreign import ccall safe minisat_solve :: Solver -> Int -> Ptr (Lit) -> IO (Bool)

它导入一个如下所示的函数:

int minisat_solve(minisat_solver *s, int len, minisat_Lit *ps)

根据文档,我的理解是,当 emscripten 导出一个接受或返回指针的函数时,该指针将变成 JavaScript 数字类型。

ghcjs 文档表明,应该可以通过适当包装 JavaScript 函数来保留现有的外部导入。然而,ghcjs 将指针类型表示为大致由 JavaScript 对象和数字组成的一对。

我认为包装代码应该大致是

function h$minisat_solve(...){
   ...
   minisat_solve(...)
   ...
}

function minisat_solve = Module.cwrap('minisat_solve',...,...)
Run Code Online (Sandbox Code Playgroud)

但我对类型不匹配感到困惑。

ccall因此,挑战如下:使用ghcjs上面的包装器代码作为示例(或者反例,如果我完全错误的话)解释如何正确包装 emscripten 导出以供导入

javascript c haskell emscripten ghcjs

5
推荐指数
1
解决办法
121
查看次数

Web Worker 中的 Emscripten WASM:“模块不是对象或函数”

我正在尝试按照教程在网络工作人员中运行 emscripten 构建的网络程序集。

当我实例化我的模块时,我得到了WebAssembly Instantiation: Import #9 module="global" error: module is not an object or function.

这是我的代码,用于生成一个工作程序并向其发送已编译的模块:

var g_worker = new Worker('worker.js');

WebAssembly.compileStreaming(fetch('my_module.wasm'))
    .then(module => {
        g_worker.postMessage(module);
    });
Run Code Online (Sandbox Code Playgroud)

工人.js:

self.onmessage = function (evt) {
    var module = evt.data;
    var config = {
        env: {
            memoryBase: 0,
            tableBase: 0,
            memory: new WebAssembly.Memory({initial: 256}),
            table: new WebAssembly.Table({initial: 0, element: 'anyfunc'})
        },
        imports: {
            imported_func: function(arg) {
                console.log(arg);
            }
        }
    };

    WebAssembly.instantiate(module, config);
}
Run Code Online (Sandbox Code Playgroud)

我用这些标志构建我的模块:

-I include \
-I …
Run Code Online (Sandbox Code Playgroud)

javascript web-worker emscripten webassembly

5
推荐指数
1
解决办法
3442
查看次数

Clang 发出有关不支持的 __declspec 属性的警告

我一直在尝试将第三方库链接到我的程序。工具链使用 Clang 4.0.0 进行编译(emscripten 1.37.19 在工具链中使用 clang)。我收到有关 __declspec 的错误,查找后发现我需要将 -fdeclspec 参数添加到 clang 中。但是,现在我收到此警告:

warning: __declspec attribute 'dllimport' is not supported [-Wignored-attributes]
Run Code Online (Sandbox Code Playgroud)

Clang 4.0 文档说应该支持这个属性。我在这里错过了什么吗?

c++ clang emscripten

5
推荐指数
0
解决办法
4404
查看次数