我正在尝试从C++库生成JavaScript包装器(以便在Web浏览器中可以在客户端使用C++代码),但我不确定哪种工具最适合此目的.使用Emscripten,是否可以从C++库生成JavaScript库,以便可以在JavaScript中调用C++函数?
我使用相同的C++代码渲染相同的场景,一次使用Windows上的原生OpenGL,一次使用Emscripten到WebGL.场景中的所有内容看起来完全相同,除非我使用alpha!= 1.0渲染内容.区别如下:

蓝色立方体颜色是(0.0, 0.0, 1.0, 0.5)
用于渲染立方体的着色器除了绘制颜色之外什么都不做.
右边是OpenGL的外观,是预期的结果,只有蓝色,半透明.左边是Emscripten + WebGL的外观.看起来实际上呈现的颜色(0.5, 0.5, 1.0, 0.5)
我使用的混合功能是标准:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Run Code Online (Sandbox Code Playgroud)
WebGL中的alpha存在某种差异吗?什么可能导致这种情况发生?
我有一个wasm进程(从c ++编译),用于处理Web应用程序中的数据。假设必要的代码如下所示:
std::vector<JSONObject> data
for (size_t i = 0; i < data.size(); i++)
{
process_data(data[i]);
if (i % 1000 == 0) {
bool is_cancelled = check_if_cancelled();
if (is_cancelled) {
break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码基本上“运行/处理查询”,类似于SQL查询界面:
但是,查询可能需要几分钟才能运行/处理,并且在任何给定时间,用户都可以取消其查询。取消过程将在运行wasm的service Worker之外的常规javascript / web应用程序中进行。
My question then is what would be an example of how we could know that the user has clicked the 'cancel' button and communicate it to the wasm process so that knows the process has been cancelled so it can exit? Using …
当我想在"普通"程序中使用库时,我用apt安装它们
apt-get install libjsoncpp-dev
apt-get install libassimp-dev
Run Code Online (Sandbox Code Playgroud)
然后在CMakeLists.txt中使用FIND_LIBRARY
FIND_LIBRARY(JSONCPP_LIBRARY NAMES jsoncpp)
TARGET_LINK_LIBRARIES(hello ${JSONCPP_LIBRARY})
FIND_LIBRARY(ASSIMP_LIBRARY NAMES assimp)
TARGET_LINK_LIBRARIES(hello ${ASSIMP_LIBRARY})
Run Code Online (Sandbox Code Playgroud)
在使用emscripten进行编译时,我显然必须以另一种方式安装库.我创建了一个目录$ HOME/emscripten-prefix,并使用--prefix = $ HOME/emscripten-prefix手动编译为静态库,并尝试使用CMAKE_INSTALL_PREFIX来查看该目录(类似于CMAKE_PREFIX_PATH):
cmake \
-DCMAKE_TOOLCHAIN_FILE=$EMSCRIPTEN/cmake/Platform/Emscripten.cmake \
-DCMAKE_BUILD_TYPE=Debug \
-G "Unix Makefiles" \
-DCMAKE_INSTALL_PREFIX=$HOME/emscripten-prefix
Run Code Online (Sandbox Code Playgroud)
不幸的是它没有用.strace透露,CMake会将CMAKE_FIND_ROOT_PATH(在$ EMSCRIPTEN/cmake/Platform/Emscripten.cmake中设置为"$ {EMSCRIPTEN_ROOT_PATH}/cmake")添加到所有路径.我尝试用-DCMAKE_FIND_ROOT_PATH更改它,但Emscripten.cmake覆盖了它.
这样做的正确方法是什么?我想我可以通过创建一个复制Emscripten.cmake并修改CMAKE_FIND_ROOT_PATH的脚本来构建它,但这听起来像是错误的方式.
我想将一个Javascript对象从JS传递回C++类/方法.我有以下简单的代码片段,它不起作用:
// Access JS objects in C++ like C++ objects
#include "emscripten/val.h" //Causing errors !
using namespace emscripten;
int main() {
val Math = val::global("Math");
return Math.call("abs", -10); // returns 10
}
Run Code Online (Sandbox Code Playgroud)
我使用以下代码在Windows上使用emscripten进行编译:
cmd> emcc Access_Objects.cpp
我得到了很大的错误记录:
In file included from Access_Objects.cpp:2:
In file included from C:\Program Files\Emscripten\emscripten\1.16.0\system\inclu
de\emscripten/val.h:4:
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:2
4:5: error:
unknown type name 'constexpr'
constexpr bool has_unbound_type_names = true;
^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:2
4:15: error:
expected unqualified-id
constexpr bool has_unbound_type_names = true;
^
C:\Program Files\Emscripten\emscripten\1.16.0\system\include\emscripten/wire.h:5
6:21: error:
use …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用Emscripten的线程,我不明白它是如何工作的.我已经阅读了一些关于网络工作者的文章,我不太清楚.
当我查看"tests"文件夹时,我可以看到pthread的东西.
我正在使用"std :: thread"并收到以下错误:
unresolved symbol: pthread_create
Run Code Online (Sandbox Code Playgroud)
我是否必须使用Web worker而不是默认线程?
谢谢!
我注意到,使用emscripten,即使是相对较小的C++文件也可以很快变成相当庞大的JavaScript文件.例:
#include <memory>
int main(int argc, char** argv) {
std::shared_ptr<int> sp(new int);
}
Run Code Online (Sandbox Code Playgroud)
使用像这样的命令用最近的emsdk编译它
em++ -std=c++11 -s DISABLE_EXCEPTION_CATCHING=1 -s NO_FILESYSTEM=1 \
-s NO_BROWSER=1 -s NO_EXIT_RUNTIME=1 -O3 -o foo.js foo.cc
Run Code Online (Sandbox Code Playgroud)
生成的文件超过400k.随着-g抛出我可以做
grep -n '^function _' foo.js | c++filt -_
Run Code Online (Sandbox Code Playgroud)
看看我们在那里有什么样的功能.这里有些例子:
std::__1::moneypunct<char, false>::do_thousands_sep() const
std::__1::locale::~locale()
std::__1::basic_string<wchar_t, …>::~basic_string()
std::__1::time_get<…>::__get_day(…) const
std::__1::codecvt<wchar_t, char, __mbstate_t>::codecvt(unsigned int)
std::__1::locale::__imp::install(std::__1::locale::facet*, long)
_printf_core
Run Code Online (Sandbox Code Playgroud)
我自己并没有打电话给任何人,但是所有的功能都包括在内.可能其中许多都包含在一些虚拟功能表中.其他可能是由于一些静态初始化器.
如果这是正常的代码链接到我的硬盘驱动器上的某个共享库; 我不反对.但只需要一个共享指针,就可以传输半兆字节的JavaScript代码?必须有办法避免这种情况.
我正在尝试一个简单的例子,用JavaScript调用编译为.wasm的C函数.
这是counter.c文件:
#include <emscripten.h>
int counter = 100;
EMSCRIPTEN_KEEPALIVE
int count() {
counter += 1;
return counter;
}
Run Code Online (Sandbox Code Playgroud)
我用它编译了它emcc counter.c -s WASM=1 -o counter.js.
我的main.jsJavaScript文件:
Module['onRuntimeInitialized'] = onRuntimeInitialized;
const count = Module.cwrap('count ', 'number');
function onRuntimeInitialized() {
console.log(count());
}
Run Code Online (Sandbox Code Playgroud)
我的index.html文件只加载正文中的两个.js文件,没有别的:
<script type="text/javascript" src="counter.js"></script>
<script type="text/javascript" src="main.js"></script>
Run Code Online (Sandbox Code Playgroud)
它工作正常/打印101到控制台,但当我将counter.c文件移动到一个wasm子目录,用emscripten重新编译并更新script标签src="wasm/counter.js",counter.js脚本尝试counter.wasm从根目录而不是wasm子目录加载,我得到错误:
counter.js:190 failed to asynchronously prepare wasm: failed to load …
我无法在另一个 JavaScript 文件中调用 C 函数,它给出错误“在运行时初始化之前调用”, 请参阅此链接
我按照给定链接中的描述在 emscripten 中编译了 C 代码,并在 test.js 文件中使用了生成的 asm.js 文件。用于生成 asm 的命令:-
emcc test/hello.cpp -o hello.html -s EXPORTED_FUNCTIONS="['_int_sqrt']" -s EXPORTED_RUNTIME_METHODS="["ccall", "cwrap"]"
Run Code Online (Sandbox Code Playgroud)
test.js 文件中的代码:
var Module = require('./asm.js');
var test = Module.cwrap('int_sqrt', 'number', ['number']);
console.log(test(25));
Run Code Online (Sandbox Code Playgroud)
当我运行时node test出现错误
Run Code Online (Sandbox Code Playgroud)abort(Assertion failed: native function `int_sqrt` called before runtime initialization)
每当我使用 emscripten 编译 C 代码时,emcc main.c -o index.html都会生成一个 html 文件,其中包含其徽标、一些按钮和控制台。但我不想要那些。我只想要可以显示 SDL 渲染内容的画布。
我做了一些研究,并在堆栈溢出中发现了这个问题。显然你必须输入emcc --shell-file一些模板 html 作为参数。
所以我制作了一个模板html文件,如下所示
<html>
<head>
<title>Some title</title>
</head>
<body>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
但当我运行时却emcc main.c -o index.html --shell-file template.html出错了。显然 emscripten 寻找一些类似的想法 - {{{ SCRIPT }}}。
所以我添加到了{{{ SCRIPT }}}我的身体里。它编译得很好。但是当我运行时,index.html控制台localhost:3000中出现错误,显示cannot find addEventListener of undefined.
[注意,我正在运行 SDL 程序。他们的文档中提到的
我应该怎么办?提前致谢
emscripten ×10
c++ ×6
javascript ×5
webassembly ×3
asm.js ×1
c ×1
cmake ×1
libc++ ×1
llvm-clang ×1
opengl ×1
pthreads ×1
sdl ×1
web-worker ×1
webgl ×1