-
2020-12-24 13:43:50
我正在使用webassembly,到目前为止,我能够管理emscripten将我的测试c项目编译为wasm文件
em提供了2个文件,即
mainTest.js mainTest.wasm
当我在我的html页面加载mainTest.js然后我得到一个名为的Java脚本对象
“模块”.
我确实找到了如何从javascript调用c / wasm方法,例如:
var myTestInteger = Module._callMyTestMethod();
并从中读取字符串
Module.wasmMemory.buffer
,但我不明白如何从C代码调用javascript.
即我希望能够像这样做:
#ifdef __cplusplus
extern "C" {
#endif
extern void testExternJSMethod();
int main()
{
cout << " Hello From my Test1 !" << endl;
testExternJSMethod();
return 0;
}
int EMSCRIPTEN_KEEPALIVE callMyTestMethod(){
return 26;
}
#ifdef __cplusplus
}
#endif
我正在加载另一个名为utils.js的js文件中的my js方法testExternMethod
function testExternMethod() {
console.log("Hello from testExternMethod!" + )
}
在这里我想从c调用JavaScript testExternJSMethod.
当我在Firefox中运行页面时,在调试器控制台中获得“-1”.
那么我在这种情况下缺少什么?不幸的是,Mozilla文档只给出了那些S表达式而不是C表示的例子.
我在例子中缺少什么?即在c中我用extern关键字定义了方法,即
extern void testExternJSMethod();
但我觉得这不是我必须做的全部.
我相信我应该以某种方式将该java脚本方法以某种方式链接到模块,但我不知道如何.
Module.asm给了我出口.哪种方法调用应该给我进口?因为我相信这个_testExternJSMethod()应该在某些导入方法中,我无法弄清楚如何实现它.
解决方法:
我不完全确定您的用例,但是您缺少能够使用函数testExternalJSMethod的重要步骤.你有两个选择:
选项1 – 图书馆
1 – 用c / c定义你的功能.
extern void testExternalJSMethod();
2 – 创建一个名为myLibrary.js的文件
3 – 需要使用以下代码将JS函数添加到库文件中的LibraryManager:
function makeAlert(text) {
alert(text);
}
if (typeof mergeInto !== 'undefined') mergeInto(LibraryManager.library, {
testExternalJSMethod: function() {
makeAlert("Hello world");
}
});
4 – 如果testExternalJSMethod依赖于其自身范围之外的任何内容(例如,上面的makeAlert),请确保在html页面中包含该脚本
5 – 在emcc命令中添加选项–js-library,并在myLibrary.js的相对路径后立即添加
emcc ... --js-library myLibrary.js
选项2 – 传递指针
1 – 在c / c中定义你的javascript函数类型
typedef void testExternalJSMethod()
2 – 无论你想在哪里使用这个函数,接受一个int参数,它将是函数指针,并将指针强制转换为你的函数
void passFnPointer(int ptr) {
((testExternalJSMethod*)ptr)();
}
3 – 使用emscripten的addFunction()并存储其返回值(指针在c / c中)
var fnPtr = Module.addFunction(function () {
alert("You called testExternalJSMethod");
});
4 – 使用步骤3中存储的指针值传递给我们的函数passFnPointer
var passFnPointer = Module.cwrap('passFnPointer', 'undefined', ['number']);
passFnPointer(fnPtr);
5 – 向emcc命令添加选项-s RESERVED_FUNCTION_POINTERS
emcc ... -s RESERVED_FUNCTION_POINTERS=10
结论
在完成其中一个选项中的所有步骤之后,您将能够通过c / c调用testExternalJSMethod()而无需使用emscripten_run_script()或EM_ASM()
标签:javascript,c11,emscripten,webassembly
来源: https://codeday.me/bug/20190715/1464914.html
更多相关内容 -
JavaScript 调用 WebAssembly 方法
2021-11-19 16:04:42WebAssembly 在线Editor WebAssembly Studiohttps://webassembly.studio/C源码: WASM_EXPORT ...JS调用 fetch('./math.wasm').then(response => response.arrayBuffer() ).then( bytes =&g...WebAssembly 在线Editor
WebAssembly Studiohttps://webassembly.studio/
https://webassembly.studio/ C源码:
WASM_EXPORT int add( int a, int b){ return a + b; }
JS调用
fetch('./math.wasm').then(response => response.arrayBuffer() ).then( bytes => WebAssembly.instantiate(bytes) ).then( results => { instance = results.instance; const add = instance.exports.add; int result = add(1, 2); console.log(" 1 + 2 = " + result ); }).catch(console.error);
-
WebAssembly调用二进制文件(wasm)
2022-04-08 16:05:13调用.wasm格式文件 JavaScript使用WebAssembly WebAssembly 二进制文件 WebAssembly Examples -
使用Webassembly在浏览器中本地合并PDF-JavaScript开发
2021-05-26 02:50:28本地PDF使用Webassembly在浏览器中编辑PDF。 您的文件不会离开系统,也不会发送到另一台服务器。Localpdf.tech Local PDF使用Webassembly在浏览器中编辑PDF。 您的文件不会离开您的系统,也不会发送到另一台服务器。... -
WebAssembly编程实践(2.1)JavaScript调用C函数
2018-11-13 18:40:09说明:本系列文章转载自《C/C++面向wasm编程——Emscripten工程实践》系列教程(名字太长,转载以《WebAssembly编程实践》为题)。本教程原文地址:https://3...说明:本系列文章转载自《C/C++面向wasm编程——Emscripten工程实践》系列教程(名字太长,转载以《WebAssembly编程实践》为题)。
本教程原文地址:https://3dgen.cn/cppwasm-book/。
作者:丁尔男,Github @3dgen
作者:柴树杉,Github @chai2010,Twitter @chaishushan
项目地址:https://github.com/3dgen/cppwasm-book
----------------------------------------------------------------------------------
2.1 JavaScript调用C函数
一个具备实用功能的WebAssembly模块,必然提供了供外部调用的函数接口。在1.3中,我们展示了通过
Module._main()
调用C/C++入口main()
函数的方法——假如main()
函数存在的话。本节将介绍普通C函数导出,供JavaScript使用的方法。2.1.1 定义函数导出宏
为了方便函数导出,我们需要先定义一个函数导出宏,该宏需要完成以下功能:
使用C风格符号修饰。我们知道,由于引入了多态、重载、模板等特性,C++语言环境下的符号修饰策略(既函数、变量在最终编译成果中的名字的生成规则)非常复杂,并且不同的C++编译器有着各自的符号修饰策略,如果不做额外处理,我们在C++中创建函数的时候,很难预知它在最终编译成果中的名字——这与C语言环境完全不同。因此当我们试图将
main()
函数之外的全局函数导出至JavaScript时,必须强制使用C风格的符号修饰,以保持函数名称在C/C++环境以及JavaScript环境中有统一的对应规则。避免函数因为缺乏引用而导致在编译时被优化器删除。如果某个导出函数仅供JavaScript调用,而在C/C++环境中从未被使用,开启某些优化选项(比如
-O2
以上)时,函数有可能被编译器优化删除,因此需要提前告知编译器:该函数必须保留,不能删除,不能改名。为了保持足够的兼容性,宏需要根据不同的环境——原生NativeCode环境与Emscripten环境、纯C环境与C++环境等——自动切换合适的行为。
info
main()
作为C/C++程序的主入口,其符号修饰策略是特殊的,因此即使在C++中不作特殊约束,其最终的符号仍然是_main()
,无需按上述第1点进行处理。tips 正如序中提到的,编写既可以在C/C++原生NativeCode环境中使用、又可以在Emscripten环境中使用的“对编译目标不敏感”的模块是本书坚持的理念,上述第3点要求正是该理念的产物。后续章节同理,不再赘述。
为了满足上述要求,定义
EM_PORT_API
宏如下:#ifndef EM_PORT_API# if defined(__EMSCRIPTEN__)# include <emscripten.h># if defined(__cplusplus)# define EM_PORT_API(rettype) extern "C" rettype EMSCRIPTEN_KEEPALIVE# else# define EM_PORT_API(rettype) rettype EMSCRIPTEN_KEEPALIVE# endif# else# if defined(__cplusplus)# define EM_PORT_API(rettype) extern "C" rettype# else# define EM_PORT_API(rettype) rettype# endif# endif#endif
在上述代码中:
__EMSCRIPTEN__
宏用于探测是否是Emscripten环境__cplusplus
用于探测是否C++环境EMSCRIPTEN_KEEPALIVE
是Emscripten特有的宏,用于告知编译器后续函数在优化时必须保留,并且该函数将被导出至JavaScript
使用
EM_PORT_API
定义函数声明:EM_PORT_API(int) Func(int param);
在Emscripten中最终将被展开如下:
#include <emscripten.h>extern "C" int EMSCRIPTEN_KEEPALIVE Func(int param);
2.1.2 在JavaScript中调用C导出函数
根据1.3中对胶水代码的分析,我们知道JavaScript环境中的Module对象已经封装了C环境导出的函数,封装方法的名字是下划线
_
加上C环境的函数名。例如我们创建C代码文件export1.cc
如下://export1.cc#ifndef EM_PORT_API# if defined(__EMSCRIPTEN__)# include <emscripten.h># if defined(__cplusplus)# define EM_PORT_API(rettype) extern "C" rettype EMSCRIPTEN_KEEPALIVE# else# define EM_PORT_API(rettype) rettype EMSCRIPTEN_KEEPALIVE# endif# else# if defined(__cplusplus)# define EM_PORT_API(rettype) extern "C" rettype# else# define EM_PORT_API(rettype) rettype# endif# endif#endif#include <stdio.h>EM_PORT_API(int) show_me_the_answer() { return 42; } EM_PORT_API(float) add(float a, float b) { return a + b; }
使用emcc命令将其编译为wasm:
emcc export1.cc -o export1.js
创建页面
export1.html
如下:<!doctype html><html> <head> <meta charset="utf-8"> <title>Emscripten:Export1</title> </head> <body> <script> Module = {}; Module.onRuntimeInitialized = function() { console.log(Module._show_me_the_answer()); console.log(Module._add(12, 1.0)); } </script> <script src="export1.js"></script> </body></html>
发布并使用浏览器打开上述网页后,我们将在开发者面板的控制台得到以下输出:
42 13
需要注意的是,JavaScript是弱类型语言,在调用函数时,并不要求调用方与被调用方的签名一致,这与C/C++有本质性的不同。例如在C环境中,以下调用都不符合语法:
int k = show_me_the_answer(10);float f1 = add(12, 12, 12);float f2 = add(12);
但是在JavaScript环境中,如果给出的参数个数多于函数形参个数,多余的参数被舍弃(从左至右);如果参数个数少于形参个数,不足的参数会自动以
undefined
填充。因此下列JavaScript调用都是合法的:console.log(Module._show_me_the_answer(10)); console.log(Module._add(2, 3, 4)); console.log(Module._add(12));
其输出为:
42 5 NaN
注意第三个调用,虽然语法上是合法的,但是由于缺少的参数以
undefined
填充而不是0值填充,因此函数返回结果为NaN
。tips 注意我们在页面中使用了1.3中介绍的
onRuntimeInitialized
回调的方式注入测试代码。为了省略无关信息方便阅读,在不产生歧义的情况下后续章节将不再重复列出回调注入的完整代码以及EM_PORT_API
宏的定义。WebAssembly编程实践(1.2)Hello World!
WebAssembly编程实践(1.1)安装Emscripten
欢迎关注玄说前端公众号
QQ群:850038125
-
WebAssembly之js调用c/c++代码
2020-05-22 12:25:14} } script> <script async type="text/javascript" src="test.js">script> body> html> nodejs调用: ex.js: let testModule = require('./test.js'); testModule.onRuntimeInitialized = function () { test...安装emscripten
windows系统 建议采用wsl安装比较方便;
示例
test.c:
#include <stdio.h> #include <emscripten/emscripten.h> int EMSCRIPTEN_KEEPALIVE myFunction(int argc, char **argv) { printf("这是一个测试函数\n"); return 0; }
编译: 会生成test.js test.wasm;(详细编译命令看官网)
emcc test.c -o test.js
html调用:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> window.onload = function () { // 初始化模块后的调用 Module.onRuntimeInitialized = function () { _myFunction(); } } </script> <script async type="text/javascript" src="test.js"></script> </body> </html>
nodejs调用:
ex.js:
let testModule = require('./test.js'); testModule.onRuntimeInitialized = function () { testModule._myFunction(); }
node ex.js
相关网址:
emscripten官网;
opencv.js; (一个通过emscripten编译opencv的js库 ) -
WebAssemblyOpenGL:带有WebAssembly + OpenGL + Webpack的C ++项目
2021-05-14 11:09:57WebAssembly和OpenGL(WIP) 这是一个示例示例,说明如何使用Emscripten移植典型的OpenGL项目以为浏览器生成.wasm文件。 编译与服务 请按照的步骤来准备编译WebAssembly Git克隆 cd到新克隆目录的根目录 使用... -
WebAssembly 对比 JavaScript 及其使用场景
2018-05-16 20:00:00如果你想在 WebAssembly 模块内访问一些指定平台的接口,你必须得通过 JavaScript 来进行调用。 举个栗子,如果你想要使用 console.log ,你就得通过JavaScript 而不是 C++ 代码来进行调用。而这些 JavaScript 调用... -
WebAssembly从wasm调用JavaScript方法,即在C ++代码中调用
2021-07-16 15:50:57I was playing with WebAssembly and so far and I was able to manage emscripten compile my test C++ project to wasm fileem++ provides me 2 files i.e.mainTest.js mainTest.wasmWhen I load mainTest.js in .... -
js_ffi-一个用于调用javascript的FFI库-Rust开发
2021-05-27 19:56:55js_ffi该库在运行时使用Web程序集在浏览器中创建javascript的桥梁外国函数接口(FFI)库用于在运行时使用Web程序集在浏览器中javascript的桥梁用于从Web Assembly调用许多编程语言的Javascript函数,没有代码生成或... -
WebAssembly之使用JS调用C/C++接口
2022-04-07 12:01:51如果想在C/C++代码中定义一个需要从JavaScript调用的函数,可以使用Emscripten 的ccall()函数并使用EMSCRIPTEN_KEEPALIVE声明(它将添加函数到导出函数列表)来完成。 代码创建 创建一个test.c文件: #include <... -
Golang-WASM为Go和JavaScript开发人员提供了与WebAssembly一起使用的简单,全面的API和绑定。-Golang开发
2021-05-26 18:57:25Golang-WASM为Go和JavaScript开发人员提供了一个简单,全面的API和绑定,可与WebAssembly一起使用。Go WebAssembly为JS DOM API提供了桥梁和绑定。 由Ortix团队撰写-Hamza Ali和Chan Wen Xu。 GOOS = js GOARCH = ... -
JavaScript也能写WebAssembly
2018-12-21 05:34:16只闻其名,从未实践过的WebAssembly。 照我的想法,做前端开发的大多熟悉脚本语言,不精通C、C++、rust等语言。 那么有一个方法可以用js写了源码编译成webassembly就好了。于是找了好久找到了walt这个东西。 walt ... -
从 node.js Web 应用中调用 WebAssembly 函数 | WebAssembly 入门教程
2020-03-20 20:33:08文中所有的代码都可以在 ...在之前的教程中,我们讨论了如何从 Web 浏览器中的 JavaScript 应用程序访问 WebAssembly 函数。 WebAssembly 快问快答 Rust 的 Hello world | WebAssembl... -
JS调用C的填坑之路,通过WebAssembly
2018-11-23 17:34:52JS如何调用C函数接口(文章中的图片不知道为何无法拷贝,不过都是些错误提示,影响不大,所有有部分图片没有上传) 参考案例1:https://blog.csdn.net/pkx1993/article/details/79550180(代码有点小问题,有部分... -
WebAssembly,JavaScript链接在Firefox中变得更快
2020-05-15 13:43:54Mozilla的最新版Firefox浏览器beta版本Firefox Nightly使WebAssembly二进制格式和JavaScript之间的调用更快,因此更容易组合这两种语言。 WebAssembly可以作为JavaScript在Web开发中的伴侣,承担性能密集型任务。 ... -
wasm-examples:WebAssembly示例
2021-01-30 12:48:44Web装配示例 各种WebAssembly的示例。可以使用以下激进版浏览器运行。 黄色的Chrome( ) 紫色的Safari( ) 深蓝色的Firefox( ),依然需要... :在wasm中调用javascript API。 :把Rust编译成WebAssembly的例子。 -
How Javascript works (Javascript工作原理) (六) WebAssembly 对比 JavaScript 及其使用场景
2019-09-23 22:55:59允许在网络应用中使用除JavaScript的语言以外的语言(比如C,C++,Rust及其他)来编写应用程序,然后编译成(提早)WebAssembly。 这是 JavaScript 工作原理的第六章。 现在,我们将会剖析 WebAssembly 的工作原理... -
使用 MATLAB Coder 生成 JavaScript:使用 MATLAB Coder 从 MATLAB 项目创建 JavaScript/WebAssembly 应用...
2021-05-29 06:23:49结合使用 MATLAB Coder Add-On 和 Emscripten 编译器生成 JavaScript,可将您的 MATLAB 函数转换为高性能的客户端 JavaScript/WebAssembly 应用程序和库。 生成的代码可以在任何现代浏览器中编译、嵌入和运行; 包括... -
Dynamsoft vs Scandit: 基于WebAssembly的JavaScript Barcode SDK深度评测
2020-08-27 16:39:19Dynamsoft和Scandit这两家公司都开发了基于WebAssembly的条形码SDK,可以让Web应用的扫码性能接近原生应用。我们可以从hello world入手,来深度体验下这两个SDK之间的差异。 Hello World快速入门 Dynamsoft 网址:... -
How Javascript works (Javascript工作原理) (八) WebAssembly 对比 JavaScript 及其使用场景
2019-09-23 22:56:04可以在每次页面加载的时候,任意调用 register() -浏览器会检测 service worker 是否已经注册从而进行适当地处理。 register() 方法里面需要特别注意的地方即 Service Worker 文件地址。当前示例是在... -
qt界面嵌入web_使用Qt WebAssembly而不是JavaScript创建Web用户界面
2020-07-15 12:25:19qt界面嵌入web 当我第一次听说WebAssembly以及使用Qt创建Web用户界面的可能性时(就像在普通C ++中一样),我决定更深入地研究该技术。 我的开源项目Pythonic完全基于Python(PyQt),并且在工作中使用C ++。 因此... -
JWebAssembly:Java字节码到WebAssembly编译器
2021-01-31 11:39:07内存管理-当前在JavaScript端具有polyfill 调用静态方法调用 调用实例方法调用 调用接口方法调用 调用动态方法调用(lambda) 调用默认方法调用 字符串支持 简单类对象支持 静态构造函数 -
aotjs:针对WebAssembly和本机的实验性提前JavaScript编译器
2021-05-17 16:00:39将JavaScript静态编译为LLVM位码本机和基于WebAssembly的执行 内存安全和沙箱JS代码不会影响未暴露给它的东西 代码小 比口译员表现更好 小型但标准的JS语言实现面向初学者的ES6左右 从主机调用JS运行时的能力 从主机... -
js调用c/cpp函数——WebAssembly入门
2017-08-31 09:55:35参考网站:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly http://kripken.github.io/emscripten-site/ 2.WebAssembly简介 WebAssembly是实验性代码,为.... -
How Javascript works (Javascript工作原理) (七) WebAssembly 对比 JavaScript 及其使用场景
2019-09-23 22:56:01个人总结: 1.webworkers实现了用多线程浏览器来进行多线程操作js的能力。 2.web workers不能操作dom,...这是 JavaScript 工作原理的第七章。 现在,我们将会剖析 Web Workers:我们将会综合比较不同类型的 wo... -
webAssembly系列--webAssembly初探究竟
2019-06-14 13:36:58一、前言 自从JavaScript诞生开始,到现在开始变成流行的编程语言,背后的是web发展所推动的。...二、为什么需要WebAssembly 针对以上的问题,JavaScript出现了一些代替语言,比如: (1)微软的TypeSc...