使用Emscripten开发网页应用的注意事项

一.小心int64

  • 导出C/C++函数包含int64

WebAssembly原生(c/c++)支持int64位整型数算术运算。

JavaScript只有一种数值类型:number——等同于C语言中的doubleJavaScript本质上无法直接表达64位整型数,因此目前的WebAssembly规范中存在这么一条尴尬的限制:

info WebAssembly导出函数不能使用64位整型数作为参数或返回值一旦在JavaScript中调用参数或返回值类型为64位整型数的WebAssembly函数,将抛出TypeError,详见《WebAssembly标准入门》3.7节。

由于该限制的存在,Emscripten做了如下妥协:

当导出函数的某个参数为64位整型数时,将其拆分为低32位、高32位两个参数进行传送;

当导出函数的返回值为64位整型数时,在JavaScript中仅能接收其低32位。

例如下列C函数定义:

int64_t func(int64_t a, int64_t b)

导出至JavaScript后将变为:

int32_t func(int32_t a_lo, int32_t a_hi, int32_t b_lo, int32_t b_hi)

其中a_lo/a_hi分别为a的低32位/高32位;b_lo/b_hi类同。

例如C代码如下:

//int64_exp.cc
EM_PORT_API(int64_t) i64_add(int64_t a, int64_t b) {
	int64_t c = a + b;
	printf("a:%lld, b:%lld:, a+b: %lld\n", a, b, c);
	return c;
}

int main() {
	printf("main():");
	printf("%lld\n", i64_add(9223372036854775806, 1));
}

在JavaScript中调用导出函数i64_add()时应使用如下方法:

//int64_exp.html
	Module = {};
	Module.onRuntimeInitialized = function() {
		console.log(Module._i64_add(0xFFFFFFFE,0x7FFFFFFF, 1, 0));
	}

浏览页面后控制台输出如下: 

 

注意前两行输出对应JavaScript中的console.log(Module._i64_add(0xFFFFFFFE,0x7FFFFFFF, 1, 0));可以看到每个int64切分为2个int32后传入C代码中正确执行了加法,但返回值仅保留了低32位(0xFFFFFFFF)为-1。而后两行输出对应C中的printf("%lld\n",i64_add(9223372036854775806, 1));算术运算的结果和输出都是正确的。 

  •  向C/C++注入函数包含int64

在JavaScript中实现C函数接口时,如果该函数接口的参数包含了64位整型数,也会按照同样的方式进行低32位/高32位的拆分,例如C函数i64_func()接口如下:

//int64_imp.cc
EM_PORT_API(void) i64_func(int64_t a, int64_t b);

int main() {
	i64_func(0x7FFFFFFFFFFFFFFF, 1);
}

注入库的JavaScript方法会收到4个参数,依次为a_loa_hib_lob_hi

//pkg.js
mergeInto(LibraryManager.library, {
	i64_func: function (a_lo, a_hi, b_lo, b_hi) {
		console.log('a_lo: ', a_lo, ', a_hi:', a_hi, ', b_lo:', b_lo, ', b_hi:', b_hi);
	}
})

使用下列命令编译:

emcc int64_imp.cc --js-library pkg.js  -o int64_imp.js

浏览页面后控制台输出如下:

 

 由上述例子可见,由于JavaScript自身的缺陷,包含int64参数/返回值的C函数Emscripten中导入导出时会发生意外的形变。 修改JavaScript标准,使其原生支持64位整型数的呼声一直很高,在这一天真的到来之前,笔者的建议是:尽量不要在JavaScript与C/C++之间交换int64。 

 二.文件系统

Emscripten提供的三种同步文件系统:MEMFSIDBFSNODEFS,它们各自的特性如下表:

特性MEMFS IDBFS NODEFS 
访问本地文件系统
使用内存模拟
支持持久化存储

NODEFS只能在Node.js中使用,因此在网页应用中不推荐使用文件系统最核心的原因在于:MEMFS/IDBFS都需要占用内存来模拟文件系统。

内存是非常珍贵的硬件资源,iOS设备的内存普遍不超过4GB,用内存模拟文件系统不论从哪个角度来说,都是非常奢侈的行为。

另外,虚拟文件系统的初始化所消耗的时间也是一个需要考量的因素,体积巨大的打包文件系统的下载消耗较长的时间,这对于网页应用非常很不利。

笔者并不是说文件系统完全不能使用——使用IDBFS保存前端配置是可行的,某些快速原型使用虚拟文件系统也可以降低移植难度;但是在使用Emscripten开发网页应用模块的时候,需要特别留意32位的内存空间(4G)、低速的网络IO操作限制,这与开发本地应用时可使用的资源有数量级的差异。当所需操作的数据非常巨大的时候,最好采用按需加载、分级加载策略。

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/239533.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++模板类的介绍

C模板类的介绍 C模板类是一种通用编程技术,允许程序员创建可处理多种数据类型的通用类。通过使用模板,我们可以编写一段能够处理不同类型数据的代码,而无需为每一种数据类型单独编写特定的代码。这大大增强了代码的复用性和灵活性。 基本概念…

飞天使-linux操作的一些技巧与知识点2-TCP的三次握手以及四次挥手以及转换状态

文章目录 TCP 的三次握手四次挥手转换状态 TCP 的三次握手 第一次,客户端与服务端建立链接,需要发送请求连接的消息 第二次,服务端接口到数据后,返回一个确认的操作*(至此客户端和服务端链路建立成功) 第三…

binlog+mysqldump恢复数据(误删数据库或者表)

表删除恢复 1、准备数据 首先准备数据库环境,测试数据库为speech1,如下: 为test数据表添加3条记录,如下:三行为新加的记录,添加后将test表删除。 2、恢复数据 查看binlog日志状态 SHOW MASTER STATUS…

汽车服务行业分析:预计2028年将达到38亿元

在推进加快检验机构建设同时,综合评估检验机构数量、分布和检测能力,探索试点汽车 4S 店开展检验,提供维修、保养、车检一体化服务。汽车服务主要是指围绕汽车展开的一系列服务活动,包括维修、美容、金融等,除具有一般…

c/c++ 结构体、联合体、枚举

结构体 结构体内存对齐规则: 1、结构体的第一个成员对齐到结构体变量起始位置偏移量为0的地址处 2、其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 对齐数:编译器默认的一个对齐数与该成员变量大小的较小值。 vs 中…

【STM32】电机驱动

一、电机分类 二、直流电机的分类 1.有刷电机 2.无刷电机 3.直流减速电机 三、H桥电路 正向旋转 驱动Q1和Q4 反向旋转 驱动Q2和Q3 四、MC3386电机驱动芯片 1.基本原理图 1)前进/后退:IN1和IN2的电平顺序决定电机的正反转 2)调节速度&#…

设计未泄密,图纸有守护者——迅软DSE加密软件专题解析!

为何使用图纸加密软件? 对于许多设计单位(如:建筑设计、鞋服设计、勘察测绘、平面设计等)而言,其内部海量的设计图纸都是以电子文件的形式存在于终端电脑和服务器上。而在图纸的设计生产过程中,一般会经过…

【ArcGIS微课1000例】0079:ArcGIS Earth根据经纬坐标生成点shapefile

本文以气象台站数据的生成为例,详细介绍ArcGIS Earth中导入X、Y经纬度坐标,生成Shapefile点数据的流程。 文章目录 一、气象台站分布二、添加经纬度坐标三、符号化设置四、另存为一、气象台站分布 根据气象台站的经纬度坐标,可以很方便的在各种GIS平台上生成点,并保存为多…

Python从入门到精通七:Python函数进阶

函数多返回值 学习目标: 知道函数如何返回多个返回值 问: 如果一个函数如些两个return (如下所示),程序如何执行? 答:只执行了第一个return,原因是因为return可以退出当前函数,导致return下方的代码不执…

如何通过上下滑动实现亮度和音量调节(ArkUI)

场景说明 在音视频应用中通常可以通过上下滑动来调节屏幕亮度和音量大小,本例即为大家介绍如何实现上述UI效果。 说明: 由于当前亮度和音量调节功能仅对系统应用开发,所以本例仅讲解UI效果的实现。 效果呈现 本例效果如下: 当在…

Apollo入门与工作原理Apollo与Nacos的区别

📫作者简介:小明java问道之路,2022年度博客之星全国TOP3,专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化,文章内容兼具广度、深度、大厂技术方案,对待技术喜欢推理加验证,就职于…

【尘缘送书第七期】2023年度盘点:智能汽车 | 自动驾驶 | 车联网

【文末送书】今天推荐几本智能汽车 | 自动驾驶 | 车联网领域优质书籍。 目录 引言1 《智能汽车》2 《SoC底层软件低功耗系统设计与实现》3 《SoC设计指南》4 《蜂窝车联网与网联自动驾驶》5 《智能汽车网络安全权威指南(上册)》6 《智能汽车网络安全权威…

智能优化算法应用:基于萤火虫算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于萤火虫算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于萤火虫算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.萤火虫算法4.实验参数设定5.算法结果6.参考文…

Mybatis映射接口的动态代理实现原理

Mybatis映射接口的动态代理实现原理 在上一节中,我们介绍了MyBatis的核心配置文件加载流程,Mybatis核心配置文件加载流程详解 在文中,我们介绍了MyBatis在加载配置文件的过程中会针对每个接口类都生成一个相应的MapperProxyFactory动态代理工…

基于FPGA的视频接口之高速IO(光纤)

简介 对于高速IO口配置光纤,现在目前大部分开发板都有配置,且也有说明,在此根据自己的工作经验以及对于各开发板的说明归纳 通过高速IO接口,以及硬件配置,可以实现对于光纤的收发功能,由于GTX的速率在500Mbs到10Gbps之间,但通道高速io可配置光纤10G硬件,物理通完成,则…

【MYSQL】MYSQL 的学习教程(二)之 MYSQL 的七种连接

1. 概述 在实际开发中,大部分的情况下都不是从单表中查询数据,一般都是多张表联合查询取出最终的结果。一个业务都会对应多张表,比如:学生和班级,起码两张表 ①:连接分类(功能划分&#xff09…

漏洞复现-云安宝-云匣子Fastjson命令执行(附漏洞检测脚本)

免责声明 文章中涉及的漏洞均已修复,敏感信息均已做打码处理,文章仅做经验分享用途,切勿当真,未授权的攻击属于非法行为!文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直接或者间接的…

(第18天)RMAN Duplicate 异机复制 Oracle 数据库

RMAN Duplicate 异机复制 Oracle 数据库(第18天) RMAN Duplicate 是从 Oracle 10G 开始出现的功能,但是在 11G 时增加了很多功能,可以通过 Active Database Duplicate 和 Backup-based Duplicate 两种方法实现。 Active database duplicate 功能更加强大,不需要先对源端…

每日一题 2048. 下一个更大的数值平衡数(枚举)

乍一看没什么想法,但它的 x 是有限的,而题目规定的数值平衡数的要求很严格,相对来说只有少部分数满足要求,所以想到了枚举的方法通过寻找所有在范围内的全排列中满足数值平衡数的要求的数,找到最接近 n 的一个官方给出…

事件驱动架构 vs. RESTful架构:通信模式对比与选择

1. 通信风格 事件驱动架构(EDA) 是一种异步通信风格,组件之间通过产生和消费事件进行通信。 事件是表示系统中重大变化或事件的消息,并分发给感兴趣的组件。这种通信模型允许系统的不同部分之间进行解耦和动态交互。 组件充当事件…