asm.js和Emscripten入门教程

Web技术突飞猛进,但是有一个领域一直无法突破----游戏。

游戏的性能要求非常高,一些大型游戏连PC跑起来都很吃力,更不要提在浏览器的沙盒模型里跑了!但是,尽管很困难,许多开发者始终没放弃,希望让浏览器运行3D游戏。

本文就将介绍asm.js和Emscripten的基本用法,介绍如何将C/C++转成JS。

C/C++编译成JS有两个最大的困难。

asm.js就是为了解决这两个问题而设计的:它的变量一律都是静态类型,并且取消垃圾回收机制。除了这两点,它与JavaScript并无差异,也就是说,asm.js是JavaScript的一个严格的子集,只能使用后者的一部分语法。

一旦JavaScript引擎发现运行的是asm.js,就知道这是经过优化的代码,可以跳过语法分析这一步,直接转成汇编语言。另外,浏览器还会调用WebGL通过GPU执行asm.js,即asm.js的执行引擎与普通的JavaScript脚本不同。这些都是asm.js运行较快的原因。据称,asm.js在浏览器里的运行速度,大约是原生代码的50%左右。

下面就依次介绍asm.js的两大语法特点。

再看下面的例子。

函数的参数和返回值,都要用这种方式指定类型。

asm.js没有垃圾回收机制,所有内存操作都由程序员自己控制。asm.js通过TypedArray直接读写内存。

下面就是直接读写内存的例子。

varbuffer=newArrayBuffer(32768);varHEAP8=newInt8Array(buffer);functioncompiledCode(ptr){HEAP[ptr]=12;returnHEAP[ptr+4];}如果涉及到指针,也是一样处理。

size_tstrlen(char*ptr){char*curr=ptr;while(*curr!=0){curr++;}return(curr-ptr);}上面的代码编译成asm.js,就是下面这样。

functionstrlen(ptr){ptr=ptr|0;varcurr=0;curr=ptr;while(MEM8[curr]|0!=0){curr=(curr+1)|0;}return(curr-ptr)|0;}1.4asm.js与WebAssembly的异同如果你对JS比较了解,可能知道还有一种叫做WebAssembly的技术,也能将C/C++转成JS引擎可以运行的代码。那么它与asm.js有何区别呢?

回答是,两者的功能基本一致,就是转出来的代码不一样:asm.js是文本,WebAssembly是二进制字节码,因此运行速度更快、体积更小。从长远来看,WebAssembly的前景更光明。

但是,这并不意味着asm.js肯定会被淘汰,因为它有两个优点:首先,它是文本,人类可读,比较直观;其次,所有浏览器都支持asm.js,不会有兼容性问题。

Emscripten的底层是LLVM编译器,理论上任何可以生成LLVMIR(IntermediateRepresentation)的语言,都可以编译生成asm.js。但是实际上,Emscripten几乎只用于将C/C++代码编译生成asm.js。

首先,新建一个最简单的C++程序hello.cc。

#includeintmain(){std::cout<<"HelloWorld!"<

$emcchello.cc$nodea.out.jsHelloWorld!上面代码中,emcc命令用于编译源码,默认生成a.out.js。使用Node执行a.out.js,就会在命令行输出HelloWorld。

注意,asm.js默认自动执行main函数。

emcc是Emscripten的编译命令。它的用法非常简单。

#生成a.out.js$emcchello.c#生成hello.js$emcchello.c-ohello.js#生成hello.html和hello.js$emcchello.c-ohello.html三、Emscripten语法3.1C/C++调用JavaScriptEmscripten允许C/C++代码直接调用JavaScript。

新建一个文件example1.cc,写入下面的代码。

#includeintmain(){EM_ASM({alert('HelloWorld!');});}EM_ASM是一个宏,会调用嵌入的JavaScript代码。注意,JavaScript代码要写在大括号里面。

然后,将这个程序编译成asm.js。

$emccexample1.cc-oexample1.html浏览器打开example1.html,就会跳出对话框HelloWorld!。

Emscripten允许C/C++代码与JavaScript通信。

新建一个文件example2.cc,写入下面的代码。

#include#includeintmain(){intval1=21;intval2=EM_ASM_INT({return$0*2;},val1);std::cout<<"val2=="<

$emccexample2.cc-oexample2.html浏览器打开网页example2.html,会显示val2==42。

Emscripten提供以下宏。

下面是一个EM_ASM_ARGS的例子。新建文件example3.cc,写入下面的代码。

#include#includevoidAlert(conststd::string&msg){EM_ASM_ARGS({varmsg=Pointer_stringify($0);alert(msg);},msg.c_str());}intmain(){Alert("HellofromC++!");}上面代码中,我们将一个字符串传入JS代码。由于没有返回值,所以使用EM_ASM_ARGS。另外,我们都知道,在C/C++里面,字符串是一个字符数组,所以要调用Pointer_stringify()方法将字符数组转成JS的字符串。

接着,将这个程序转成asm.js。

$emccexample3.cc-oexample3.html浏览器打开example3.html,会跳出对话框"HellofromC++!"。

JS代码也可以调用C/C++代码。新建一个文件example4.cc,写入下面的代码。

#includeextern"C"{doubleSquareVal(doubleval){returnval*val;}}intmain(){EM_ASM({SquareVal=Module.cwrap('SquareVal','number',['number']);varx=12.5;alert('Computing:'+x+'*'+x+'='+SquareVal(x));});}上面代码中,EM_ASM执行JS代码,里面有一个C语言函数SquareVal。这个函数必须放在extern"C"代码块之中定义,而且JS代码还要用Module.cwrap()方法引入这个函数。

Module.cwrap()接受三个参数,含义如下。

除了Module.cwrap(),还有一个Module.ccall()方法,可以在JS代码之中调用C函数。

varresult=Module.ccall('int_sqrt',//C函数的名称'number',//返回值的类型['number'],//参数类型的数组[28]//参数数组);回到前面的示例,现在将example4.cc编译成asm.js。

$emcc-sEXPORTED_FUNCTIONS="['_SquareVal','_main']"example4.cc-oexample4.html注意,编译命令里面要用-sEXPORTED_FUNCTIONS参数给出输出的函数名数组,而且函数名前面加下划线。本例只输出两个C函数,所以要写成['_SquareVal','_main']。

浏览器打开example4.html,就会看到弹出的对话框里面显示下面的内容。

Computing:12.5*12.5=156.253.5C函数输出为JavaScript模块另一种情况是输出C函数,供网页里面的JavaScript脚本调用。新建一个文件example5.cc,写入下面的代码。

extern"C"{doubleSquareVal(doubleval){returnval*val;}}上面代码中,SquareVal是一个C函数,放在extern"C"代码块里面,就可以对外输出。

然后,编译这个函数。

$emcc-sEXPORTED_FUNCTIONS="['_SquareVal']"example5.cc-oexample5.js上面代码中,-sEXPORTED_FUNCTIONS参数告诉编译器,代码里面需要输出的函数名。函数名前面要加下划线。

接着,写一个网页,加载刚刚生成的example5.js。

TestFile

浏览器打开这个网页,就可以看到result==100了。

如果执行环境不是浏览器,而是Node,那么调用C函数就更方便了。新建一个文件example6.c,写入下面的代码。

#include#includevoidsayHi(){printf("Hi!\n");}intdaysInWeek(){return7;}然后,将这个脚本编译成asm.js。

$emcc-sEXPORTED_FUNCTIONS="['_sayHi','_daysInWeek']"example6.c-oexample6.js接着,写一个Node脚本test.js。

varem_module=require('./api_example.js');em_module._sayHi();em_module.ccall("sayHi");console.log(em_module._daysInWeek());上面代码中,Node脚本调用C函数有两种方法,一种是使用下划线函数名调用em_module._sayHi(),另一种使用ccall方法调用em_module.ccall("sayHi")。

运行这个脚本,就可以看到命令行的输出。

另外,由于asm.js的运行速度较快,所以一些计算密集型的操作(比如计算Hash)可以使用C/C++实现,再在JS中调用它们。

(完)

兰宇说:

阮老大好早,半年前作为一个搬运工的我被朋友带入这一行,就是因为魔兽这个游戏,虽然我不是一个游戏开发,但是看到游戏二字立马点进来,mark一下再说

svtter说:

这是打开了js机器学习之路…

邹振忠说:

我以为会顺便说一说王者荣耀的【坏笑】

铃铛说:

haobing说:

已经学不过来了,只能静静地看着你们继续前进

许杰学node说:

引用兰宇的发言:这半年多我每天晚上下班都会学到1点之后,必要的话我可以学到半夜三,四点,第二天上班精神还会很好,可是我觉得学的东西太泛,不精,也不基础,所以现在到底是先从泛到精再补基础,还是基础和泛并行,一直到精呢

我现在也是一个新人,觉得基础这东西,得从实际出发,慢慢领悟,不能太操之过急,你每天学习到1,2点,怎么会有这么多精力呢,相比较,我就惭愧多了。。。

RedNax说:

引用许杰学node的发言:我现在也是一个新人,觉得基础这东西,得从实际出发,慢慢领悟,不能太操之过急,你每天学习到1,2点,怎么会有这么多精力呢,相比较,我就惭愧多了。。。

和爱好和习惯有关,我大学时期玩魔兽的时候基本都是晚上2点睡,早上6点半起来继续奋战,因为爱好,投入进去了就不会感觉到累。我之前在工地做过放线的,基本都是每天早上6点起床在太阳下干到晚上11,12点,学徒总是被压榨的,后来做了搬运工,就是扛肥料的,一吨9元,我们一天收入大概在300左右,累了就会喝一瓶冰冻啤酒解乏,所以之前学累了,我会去买一瓶冰冻百威或者雪花和一包花生,边吃边学,每个人都会有他的亢奋点,我之前的亢奋点就是一瓶冰冻脾酒,会让我达到一个最佳状态,集中精神和不会感到疲乏.另外不管再忙,每坐一到2个小时我都会偷偷的到楼梯间爬一下楼梯,做几组俯卧撑,晚上下班的时候也会去快走一小时再做几组深蹲,这可以保持你的肺活量保持你大脑的清醒,午休是必须的,日常午休10分钟到半小时,如果当天你太累,你必须睡够一个多小时。不加班的周末最好去做有氧运动,看你个人的喜好,只要是有氧就行。还有一点,我尝试过白天疯狂学习,晚上到网吧玩游戏到3点回来,这样第二天虽然可以上班,但是效率不是一般的低,所以如果想保持一直精神集中学习的话最好戒掉游戏,否则也不要多玩,希望可以帮到你。

阿飞说:

”运行速度是原生js的50%“,到底是快了还是慢了?

rufi说:

Rust也可以编译成webasm

wZi说:

据称,asm.js在浏览器里的运行速度,大约是原生代码的50%左右。

楼上……原生代码是指nativeC,不是nativejavascript……

StruggleYang说:

瑞尔思说:

3D页游未来估计也是趋势,这边做渲染输出

YXCoder说:

千言万语汇成一句话,峰哥牛B

姜佐腾说:

之前在树莓派上用js操作gpio,因为js速度太慢会错过数据,感觉用这个有点希望了

Simon说:

WebGL,three.js估计也会火起来

哥斯拉说:

./emsdkinstallsdk-incoming-64bitbinaryen-master-64bit这一步下载速度实在太慢了,有什么其他方法吗,

xxxx说:

引用兰宇的发言:阮老大好早,半年前作为一个搬运工的我被朋友带入这一行,就是因为魔兽这个游戏,虽然我不是一个游戏开发,但是看到游戏二字立马点进来,mark一下再说

你可以寻找一些名气不是特别大,但技术能力还是有的小牛或许更加适合现在的你,也会指导你的。

刚吃了一头牛说:

刚看完再鲁会码9点才上班

杭盖说:

在浏览器的沙盒模型里跑游戏本身就是个伪命题,看了太多的技术消亡都是因为没有产生真正的社会生产力,带不来经济效应。

soyo说:

js千秋万代,一统江湖

ccwf2006说:

类型系统是C++的,内存管理是C++的。这是重新发明了一次C++啊。

Huey说:

其实现在WebGL性能上的瓶颈在于JS的运算速度吗?跟浏览器本身是否会有关联?我很想了解的是目前3D在浏览器端性能瓶颈究竟是什么?

李绍伟说:

阮老师终于开始对游戏下手了……期待!

李彦宏说:

浏览器跑些简单的H5应该可以,大型游戏太吃内存,操作系统弱了内存小了都带不上

thc说:

引用哥斯拉的发言:./emsdkinstallsdk-incoming-64bitbinaryen-master-64bit这一步下载速度实在太慢了,有什么其他方法吗,

下载x2d里面有,速度那很快!!!

Shepherdog说:

可惜asm.js没有被Safari支持,苹果似乎是一路奔向wasm(iOS11+、Safari11+),或许wasm才是未来的主角,虽然asm.js可读,可以转译成wasm,但应该没人真去读这些代码吧,可读性好不到哪里去,更多场景是开发者不希望别人看到自己的明文代码。而wasm是优化JIT阶段的字节码,类似于smali,更像二进制的机器码,更安全的分发,比asm.js更高的压缩比和执行效率,既生瑜何生亮乎?

liu说:

为什么我测的只有IE10对asm.js兼容,IE其他版本都不兼容。

大名说:

搞js的得累死,新东西多如牛毛。es6都还没掌握。

JasonHuang说:

言心说:

./emsdkinstall--build=Releasesdk-incoming-64bitbinaryen-master-64bit

请教一下,在window下怎么安装?

wurenzidi说:

"另外,浏览器还会调用WebGL通过GPU执行asm.js,即asm.js的执行引擎与普通的JavaScript脚本不同。这些都是asm.js运行较快的原因。"——————————————————————————————————————————SeriouslyGPU执行ams.js

chai2010说:

欢迎提供建议

morris说:

熊猫小侠说:

我从网上下了一个C语言的库,希望可以编译成asm.js,但现在只生成wasm,老大指教一下原因?下面是编译命令

#!/bin/bashemcccrypto/*.c-Oz\-sDISABLE_EXCEPTION_CATCHING=1\-sBINARYEN_ASYNC_COMPILATION=1\-sALIASING_FUNCTION_POINTERS=1\-sALLOW_MEMORY_GROWTH=1\-sWASM=1\-sBINARYEN=1\-sNO_EXIT_RUNTIME=1\-sASSERTIONS=1\-sSTACK_OVERFLOW_CHECK=1\-sEXPORTED_FUNCTIONS="['_cryptonight_hash']"\--post-js../web/lib/worker.js\-o../web/lib/cryptonight.js

jupiterben说:

-sWASM=1改成0

翟明说:

不知道这个东西有没有javaapplet快,好多年前的技术了

killinux说:

linwei说:

皮卡丘说:

引用阿飞的发言:”运行速度是原生js的50%“,到底是快了还是慢了?

不是原生js的50%,是c,c++,rust这些语言的50%。

hh说:

如何在react中调用生成的.js

李伟说:

111说:

"一旦JavaScript引擎发现运行的是asm.js,就知道这是经过优化的代码,可以跳过语法分析这一步,直接转成汇编语言。另外,浏览器还会调用WebGL通过GPU执行asm.js,即asm.js的执行引擎与普通的JavaScript脚本不同。这些都是asm.js运行较快的原因"

这是认真的???跳过语法分析???GPU运行JS???

马里奥说:

大家都怎么样了,我来晚了,研究wasm来了

kui-kui说:

还有更高阶的演示吗?最近在看embind但是网上的例子都说的只言片语的执行不成功

THE END
1.MicrosoftC/C++DocumentationMicrosoftLearnLearn how to use C++ to develop applications, services, and tools for your platforms and devices.https://docs.microsoft.com/lb-lu/cpp/
2.c++编译器下载c++编译器v10.2.5最新版电脑免费中文下载c++编译器采用先进的编译技术,显著提升C++代码编译速度,缩短开发周期,内置智能优化算法,自动分析代码结构,优化执行效率,减少资源消耗。支持多种操作系统平台,包括Windows、Linux、macOS等,确保代码无缝迁移。 软件特色 强大调试功能 集成先进的调试工具,支持断点、单步执行、变量监视等,助力快速定位问题。 代码分析与重构 提https://patch.ali213.net/showpatch/255635.html
3.C++高效编程网页版网页版c++,c++网页版资源这是C++高效内存管理的核心理念。 8. **性能优化**:了解如何利用编译器优化选项、手动内存管理、算法优化以及多线程并行计算等方法,可以进一步提升C++程序的执行速度。 9. **C++11及更高版本的新特性**:从C++11开始,语言引入了许多新特性,如右值引用、lambda表达式、自动类型推断(auto关键字)、并发编程工具等,https://download.csdn.net/download/lunha/4188425
4.c语言网页版在线编译器怎么用,怎样在平板上用c语言编程用编译器(一般编程程序自带)编译c语言文件编译完就可运行! 2,c 编译器怎么用 在右上角有按钮的,我用手机,也不知怎么描述,这样吧,你下中文版的,然后放鼠标到图标上,会提示的 visual c++6.0兼容c语言的! 简易c语言开发工具!打开就能编了,不用建什么文件的! 这些网上很容易找到的 谢谢请采纳! http://www.lisdn.com/mnsj/hhzs/505137.html
5.如何利用C++实现一个简单的网页爬虫程序?C++如何利用C++实现一个简单的网页爬虫程序? 简介:互联网是一个信息的宝库,而通过网页爬虫程序可以轻松地从互联网上获取大量有用的数据。本文将介绍如何使用C++编写一个简单的网页爬虫程序,以及一些常用的技巧和注意事项。 一、准备工作 安装C++编译器:首先需要在计算机上安装一个C++编译器,例如gcc或者clang。可以通过命令https://m.php.cn/faq/625768.html
6.程序员专用十大在线编译器(IDE)整理① GCC编译器资源管理器是一个交互式在线编译器,它显示编译后的C++、RISE、GO(以及更多)代码的汇编输出。 ② 地址:https://gcc.godbolt.org/ ③ 图示 编辑界面 (图 9-1) 10. plnkr edit在线编辑器 ① js的在线编辑器。 ② 地址:http://plnkr.co/edit/ https://www.51cto.com/article/600631.html
7.简单上手python爬虫-1:python or c++ 0:前置知识:关于python 1:第一个任务--下载网页 2:下载一张图片吧 3:第二个任务--有道翻译 3.0:服务器是怎么处理我们的发送的请求的? 3.1:前置芝士:URL的组成 3.2:使用有道翻译 4:关于编码的那些事 4.1:ASCII,utf-8,GB2312,unicode,ANSI有什么区别? https://www.luogu.com.cn/article/wubltxkl
8.快对作业网页版在线下载C++编译器 大小:60.33MB 版本:11.1.1 C语言编译器 大小:71.38MB 版本:11.1.1 逻辑电路模拟器 大小:26.96MB 版本:36.0.0 大学搜题酱 大小:46.60MB 版本:2.24.0 课程表达人 大小:8.45MB 版本:6.0 相关攻略 更多+ 《今日头条》解除锁定方法 《快对作业》取消收藏书单方法 《快对作业》下载答案储存路https://shouyou.3dmgame.com/android/237474.html
9.hth网页版在线登录入口官方版(2024APP)【下载次数74425】支持:winall/win7/win10/win11现在下载,新用户还送新人礼包hth网页版在线登录入口是一款经典好用的跨渠道编译器,具有才能强、经验丰富的开发团队,并且内嵌C++,C structur,支撑JSON, SSL, TCP多种现代规范,一起经过该软件,你能构建运行在GNU/Linux、Windowshttp://m.share.www.hzkzjk.com/mPa/detail/jqDmxi.html
10.asp.net技术faqasp.net基础开始Microsoft 将提供 C#、C++、VB 和 JScript 编译器。其它供应商宣布他们有意开发像 COBOL、Eiffel、Perl、Smalltalk 和 Python 等语言的 .NET 编译器。 1.11 .NET 框架符合标准化趋势吗? C# 以及称为“通用语言基础结构”的一些东西的推荐标准草案已经提交给了 ECMA。参见http://msdn.microsoft.com/net/ecma/https://www.west.cn/www/info/50613-1.htm
11.C++使用HttpRequest获取网页及UTF8转GB码旭东的博客 | C++ win C/C++程序通过Get方式获取网页源代码 [转自]http://www.cnblogs.com/coderzh/archive/2008/11/24/1340134.html 1 #include 2 #include 3 #include 4 5 #define MAXSIZE 1024 6 #pragma comment(lib, "Wininet. 913 0 0 ephemerals__ | 8天前 | 存储 编译器 C语言 【https://developer.aliyun.com/article/1218387
12.推荐一款强大的在线编译器几款优秀的支持C、C++等多种语言的在线编译器 https://www.onlinegdb.com(公号不支持外链接,请复制链接到浏览器打开) 最后,这些在线编译器对于一些初学者(不懂各种配置),或者想测试本地没有的编译环境都是非常有用的,大家有: 如果代码有错误,在线编译,也会提示: 总的来说,这款在线编译器的功能挺多,也https://www.pianshen.com/article/795354268/
13.IBM编译器开发团队的微博最新的 IBM XL C/C++ 编译器 V13.1.5 与 Fortran 编译器 V15.1.5 已经在今天正式发布啦!而且这次更新的社区版的 C/C++ 与 Fortran 编译器具有与商业版本一样的功能,如最高的优化级别 -O5,OpenMP 4.5 等等详见:O网页链接 欢迎大家去免费下载并使用性能卓越的XL编译器! 展开全文chttps://www.weibo.com/ibmcompiler
14.c语言网页版在线编译器c语言网页版在线运行c编译器-c语言的编译器是干什么用的本人不才,仅就个人意见谈谈: 1。c语言编译器哪个好?g++,icc. 小问题二:在类中对友元函数和重载的支持不是很好,虽然打了补丁,还是有点问题,最经典的一次就是我写了一个类的https://cloud.tencent.com/developer/information/c%E8%AF%AD%E8%A8%80%E7%BD%91%E9%A1%B5%E7%89%88%E5%9C%A8%E7%BA%BF%E7%BC%96%E8%AF%91%E5%99%A8
15.SNL编译器(网页版)汇编原理编译器6.0版 这是一个6.0版本的汇编语言的编译器,大家尽情的享用吧 上传者:yuzhoufeng888时间:2008-11-28 SNL语言编译器C++实现 从词法分析到目标代码生成 各个部分都有。 上传者:hhf1029时间:2012-05-02 SNL编译器java实现 学校SNL语言的编译器java实现,包括词法分析,语法分析,语义分析。有程序界面,非https://www.iteye.com/resource/lisc741-5603013
16.GCC在线编译器的使用教程是什么问答GCC是一种广泛使用的开源编译器,可以用于编译C、C++等编程语言。GCC在线编译器是指可以通过网页访问并使用GCC编译器的服务。以下是使用GCC在线编译器的一般步骤:1. 打开GCC在线编译器的https://www.yisu.com/ask/61671196.html
17.关于编程的一些术语及解释编译器(compiler) —种程序,将更强大、更流行的语言(高级语言)写的程序翻译成计算机硬件能够理解的命令(机器语言)。参见“解释器”(interpreter)。 ? 复杂性(complexity) 算法的“时间复杂性”(time complexity)指的是,当输入的数据量不断增加时,计算机完成这种算法所消耗的时间。比如,假定你要https://www.guhei.net/post/jb606