Emscripten下载
安装Emscripten:可以在Emscripten的官方网站(https://emscripten.org/)上找到安装说明。 我的踩坑记录在:WebAssembly002 emcc install + 解决 Error: Downloading URL ‘https://storage.googleapis.com/…‘ error
简单Demo
#include <stdio.h>
#include <emscripten/emscripten.h>int main(int argc, char ** argv) {printf("Hello World\n");
}#ifdef __cplusplus
extern "C" {
#endifEMSCRIPTEN_KEEPALIVE void myFunction(int argc, char ** argv) {printf("MyFunction Called\n");
}#ifdef __cplusplus
}
#endif
cmake_minimum_required(VERSION 3.17)
project(WASM)set(CMAKE_CXX_STANDARD 14)add_executable(WASM main.cpp)
以上Demo来自https://stackoverflow.com/questions/65466537/how-to-include-emscripten-emscripten-h,下面简单介绍一些重要的API
EMSCRIPTEN_KEEPALIVE(重要)
EMSCRIPTEN_KEEPALIVE
:此宏用于声明在JavaScript中可访问的函数。通过在函数定义前使用此宏,您可以确保函数不会被优化和删除。
EMSCRIPTEN_KEEPALIVE
void myFunction ( ) {
}
emscripten_run_script*
emscripten_run_script
:此函数用于在JavaScript环境中执行一段脚本。
emscripten_run_script ( "console.log('Hello, Emscripten!')" ) ;
emscripten_async_wget*
emscripten_async_wget
:此函数用于异步下载文件。
void downloadFile ( ) { emscripten_async_wget ( "https://example.com/file.txt" , "file.txt" , onComplete, onError) ;
} void onComplete ( ) { printf ( "File downloaded successfully.\n" ) ;
} void onError ( ) { printf ( "Error downloading file.\n" ) ;
}
emscripten_set_main_loop*
emscripten_set_main_loop
:此函数用于设置一个主循环,它将在每个帧上运行。
void mainLoop ( ) {
} int main ( ) { emscripten_set_main_loop ( mainLoop, 0 , 1 ) ; return 0 ;
}
使用emscripten.h 处理js输入的数组并返回处理的数组
下面是一个完整的例子,演示了如何使用emscripten.h处理JavaScript输入的数组,并返回处理的数组:
# include <emscripten.h>
int squareNumber ( int num) { return num * num;
}
EMSCRIPTEN_KEEPALIVE
int * processArray ( int * inputArray, int length) { int * outputArray = ( int * ) malloc ( length * sizeof ( int ) ) ; for ( int i = 0 ; i < length; i++ ) { outputArray[ i] = squareNumber ( inputArray[ i] ) ; } return outputArray;
} int main ( ) { return 0 ;
}
使用Emscripten编译器将该代码编译为WebAssembly模块:
emcc main.cpp -o example.html -s EXPORTED_FUNCTIONS='["_processArray","_malloc"]' -s EXPORTED_RUNTIME_METHODS='["ccall"]'
在JavaScript中使用编译好的WebAssembly模块:
const wasmModule = require ( './example.js' ) ;
let inputArray = [ 1 , 2 , 3 , 4 , 5 ] ;
let inputArrayPointer = Module. _malloc ( inputArray. length * Int32Array. BYTES_PER_ELEMENT ) ;
Module. HEAP32 . set ( inputArray, inputArrayPointer / Int32Array. BYTES_PER_ELEMENT ) ;
const outputArrayPointer = Module. ccall ( 'processArray' , 'number' , [ 'number' , 'number' ] , [ inputArrayPointer, inputArray. length] ) ;
let outputArray = Module. HEAP32 . subarray ( outputArrayPointer / Int32Array. BYTES_PER_ELEMENT , outputArrayPointer / Int32Array. BYTES_PER_ELEMENT + inputArray. length) ;
const outputJsArray = Array. from ( outputArray) ; let outputJsArray = Array. from ( outputArray) ;
console. log ( outputJsArray) ; Module. _free ( inputArrayPtr) ;
Module. _free ( outputArrayPtr) ;
代码首先加载了编译好的WebAssembly模块,然后定义了一个输入数组。接下来,使用模块的_malloc
函数将输入数组分配在内存中,并将其指针传递给C函数。使用ccall
函数调用C函数来处理输入数组,并获取处理后的数组的指针。最后,将输出数组从C格式转换为JavaScript格式,并打印了输出数组。
cg
let inputArray = [1, 2, 3, 4, 5];let inputArrayPointer = Module._malloc(inputArray.length * Int32Array.BYTES_PER_ELEMENT);
Module.HEAP32.set(inputArray, inputArrayPointer / Int32Array.BYTES_PER_ELEMENT);const outputArrayPointer = Module.ccall('hf_play_start_train', 'number', ['number', 'number'], [inputArrayPointer,1]);