在typescript浏览器端中调用C++编写的函数,WebAssembly传递指针类型的参数,以及处理指针类型的返回值。

news2024/11/15 14:07:48

首先要在Cmake工程中的cmakelists.txt文件中引入Emscripten工具链:

set(CMAKE_TOOLCHAIN_FILE "D:/CppPkg/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake")

直接看C++代码:

#include <emscripten/emscripten.h>
#include <cstdlib>


extern "C" {
	struct DataResult {
		double* dArr;
		int propCount;
	};

	EMSCRIPTEN_KEEPALIVE
	double sumArray(double* fArr, int arrLen) {
		double sum = 0.0;
		for (int i = 0; i < arrLen; i++) {
			sum += fArr[i];
		}
		return sum;
	}
	EMSCRIPTEN_KEEPALIVE
	double* vectorSum(double* vectorA, double* vectorB, int vecLen) {
		double* resArr = (double*)malloc(vecLen * sizeof(double));
		for (int i = 0; i < vecLen; i++) {
			resArr[i] = vectorA[i] + vectorB[i];
		}
		return resArr;
	}
	EMSCRIPTEN_KEEPALIVE
	DataResult* createDataResult(double* dArr, int propCount) {
		DataResult* dtRes = (DataResult*)malloc(sizeof(DataResult));
		dtRes->dArr = dArr;
		dtRes->propCount = propCount;
		return dtRes;
	}

	EMSCRIPTEN_KEEPALIVE
	double* allocateDoubleMemory(int size) {
		return (double*)malloc(size * sizeof(double));
	}
	EMSCRIPTEN_KEEPALIVE
	void freeMemory(void* dataPtr) {
		free(dataPtr);
	}
}

通过em++命令,生成MyLib.js和MyLib.wasm文件

em++ MyLib.cpp -O2 -o MyLib.js -s WASM=1 -s MODULARIZE=1 -s EXPORT_NAME="MyLibModule" -s "EXPORTED_FUNCTIONS=['_sumArray']" -s "EXPORTED_RUNTIME_METHODS=['ccall', 'cwrap']"

在WASMTest.ts中编写代码:

type ImportObject = WebAssembly.Imports;
 interface MyLibModule{
    sumArray: (fArr: number, arrLen: number) => number;
    allocateDoubleMemory: (size: number) => number;
    freeMemory: (dataPtr: number) => void;
    vectorSum: (vectorA: number, vectorB: number, vecLen: number) => number;
    createDataResult: (dArrPtr: number, propCount: number) => number;
    memory: WebAssembly.Memory;
 }

 async function loadWasmModule(memory: WebAssembly.Memory): Promise<MyLibModule>{
    const importObject: WebAssembly.Imports = {
        env: {
            memory: memory,
            emscripten_resize_heap: () => {
                console.log("emscripten_resize_heap called");
                return true;  // 这里可以返回 true 或者处理扩展内存的逻辑
            },
        }
    };
    const response = await fetch('src/lib/wasm/MyLib.wasm');
    const buffer = await response.arrayBuffer();
    const module = await WebAssembly.instantiate(buffer, importObject);
    return module.instance.exports as unknown as MyLibModule;
 }

 async function useModule(){
    const memory = new WebAssembly.Memory({ initial: 20, maximum: 1000 });
    const wasmModule = await loadWasmModule(memory);
    const pageSize = 64 * 1024;
    const totalMemory = memory.buffer.byteLength;
    const totalPages = totalMemory/pageSize;
    console.log(`Total memory: ${totalMemory} bytes (${totalPages} pages)`)
    memory.grow(100);
    console.log(`New total memory size: ${memory.buffer.byteLength} bytes`);

        const vecA = new Float64Array([1,2,3,4,5,6,9,12]);
        const vecB = new Float64Array([1,2,3,4,5,6,6,14]);
        const vecAptr = wasmModule.allocateDoubleMemory(vecA.length * 8);
        const vecBptr = wasmModule.allocateDoubleMemory(vecB.length * 8);
        const memoryBuffer = wasmModule.memory.buffer;
        const wasmVecA = new Float64Array(memoryBuffer, vecAptr, vecA.length);
        const wasmVecB = new Float64Array(memoryBuffer, vecBptr, vecB.length);
        wasmVecA.set(vecA);
        wasmVecB.set(vecB);
        const resultPtr = wasmModule.vectorSum(vecAptr, vecBptr, vecA.length);
        const wasmRes = new Float64Array(memoryBuffer, resultPtr, vecA.length);
        console.log(wasmRes)
        wasmModule.freeMemory(vecAptr);
        wasmModule.freeMemory(vecBptr);
        wasmModule.freeMemory(resultPtr);
    
        // 传递数组,返回结构体指针,从结构体指针中取数据。
        const dArr = new Float64Array([5,4,7,1,9,3,5]);
        const dArrPtr = wasmModule.allocateDoubleMemory(dArr.length * 8);
        const wasmdArr = new Float64Array(memoryBuffer, dArrPtr, dArr.length);
        wasmdArr.set(dArr);
        const resPtr = wasmModule.createDataResult(dArrPtr, dArr.length);
        const dataView = new DataView(memoryBuffer);
        const dArrResPtr =  Number(dataView.getUint32(resPtr, true));
        const propCount = dataView.getInt32(resPtr+4, true);
        const resdArr = new Float64Array(memoryBuffer, dArrResPtr, propCount);
        console.log(`return struct DataResult dArr Pointer is ${dArrResPtr}`);
        console.log(`the struct DataResult dArr value is: `);
        console.log(resdArr);
        wasmModule.freeMemory(dArrPtr);
        wasmModule.freeMemory(resPtr);
    
}
useModule();

查看浏览器打印结果:

在这里插入图片描述

第一个例子:在这里,我们传递了2个双精度浮点的数组,传递进入C++函数,然后给两个数组求和,返回的是double*类型的指针。
第二个例子:
最后是返回一个C++结构体指针,在TypeScript中通过DataView来获取内存中的地址偏移量来取得结构体中的数据,因为em++编译器是以32位来编译.cpp文件的,所以指针占4个字节。DataResult结构体第一个属性dArr是一个指针,那么就是地址偏移量0,然后以32位无符号整型取得dArr指针,通过这个指针去读取wasm中memoryBuffer中的数据,就可以得到dArr属性对应的值了。同理,通过地址偏移量+4来得到propCount属性,以32位整数读取数据即可。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

服务器——装新的CUDA版本的方法

服务器——装新的CUDA版本 一、进入 CUDA 版本列表二、根据自己服务器&#xff0c;选择对应的版本和配置三、使用管理员用户&#xff0c;运行下载和安装命令四、查看显卡驱动是否安装4.1 若安装了显卡驱动4.2 若显卡驱动没安装 参考文章 一、进入 CUDA 版本列表 CUDA Toolkit …

MFC工控项目实例之十七添加手动测试界面

承接专栏《MFC工控项目实例之十六输入信号验证》 1、在JogTest.h文件中添加代码 class CJogTest : public CDialog { public:CJogTest(CWnd* pParent NULL); // standard constructorCButtonST m_btnStart[16];CFont m_font; ... } 2、在JogTest.cpp文件中添加代码 #…

【医药行业】实施SAP有哪些医药行业GXP的合规要求和注意事项

作为实施过辉瑞和赛诺菲医药行业的项目&#xff0c;总结了如下&#xff1a; 在医药行业中&#xff0c;GxP&#xff08;Good Practices&#xff0c;良好规范&#xff09;是一系列标准与指南&#xff0c;旨在确保制药、医疗设备和生物制品的质量与合规性。GxP包括多个领域&#x…

计算机网络通关学习(一)

简介 之前我通过王道的考研课进行了计算机网络的学习&#xff0c;但是在秋招准备过程中发现之前的笔记很多不足&#xff0c;学习的知识不够深入和巩固&#xff0c;所以再重新对《图解HTTP》&《图解TCP/IP》进行深度学习后&#xff0c;总结出了此篇博客&#xff0c;由于内容…

re题(27)BUUFCTF-[MRCTF2020]Transform

BUUCTF在线评测 (buuoj.cn) 先到ida&#xff0c;先看一下字符串 找到主函数 int __cdecl main(int argc, const char **argv, const char **envp) {char Str[104]; // [rsp20h] [rbp-70h] BYREFint j; // [rsp88h] [rbp-8h]int i; // [rsp8Ch] [rbp-4h]sub_402230(argc, arg…

ai扩图用什么软件?探索五大高效工具

Hey朋友们&#xff0c;最近在社交媒体上看到不少超清晰的美图&#xff0c;是不是特别羡慕&#xff1f; 别急&#xff0c;告诉你个秘密武器——ai扩图软件。这些神器能帮你智能扩展图片内容&#xff0c;让每张图都充满细节。 想知道都有哪些好用的ai扩图软件免费吗&#xff1f…

CentOS上使用rpm离线安装Mosquitto(Linux上Mqtt协议调试工具)附资源下载

场景 Windows上Mqtt服务器搭建与使用客户端工具MqttBox进行测试&#xff1a; Windows上Mqtt服务器搭建与使用客户端工具MqttBox进行测试_微软消息队列 测试工具-CSDN博客 Windows服务器上Mqtt服务器EMQX的安装使用&#xff1a; Windows服务器上Mqtt服务器EMQX的安装使用_wi…

Objects as Points基于中心点的目标检测方法CenterNet—CVPR2019

Anchor Free目标检测算法—CenterNet Objects as Points论文解析 Anchor Free和Anchor Base方法的区别在于是否在检测的过程中生成大量的先验框。CenterNet直接预测物体的中心点的位置坐标。 CenterNet本质上类似于一种关键点的识别。识别的是物体的中心点位置。 有了中心点之…

Python青少年简明教程:tkinter库入门

Python青少年简明教程&#xff1a;tkinter库入门 tkinter是Python的标准GUI&#xff08;图形用户界面&#xff09;库。它提供了一种快速而简单的方法来创建GUI应用程序。tkinter是Python自带的&#xff0c;无需额外安装&#xff0c;随 Python 安装包一起提供。 在Python 3.x中…

Leetcode—1137. 第 N 个泰波那契数【简单】

2024每日刷题&#xff08;160&#xff09; Leetcode—1137. 第 N 个泰波那契数 记忆化搜索实现代码 class Solution { public:int tribonacci(int n) {int zero 0;int one 1;int two 1;if(n 0) {return zero;}if(n 1) {return one;}if(n 2) {return two;}int ans 0;fo…

三重因素,巨人瘦身——从 IBM中国研发部裁员讲起

如何看待IBM中国研发部裁员&#xff1f;近日&#xff0c;IBM中国宣布撤出在华两大研发中心&#xff0c;引发了IT行业对于跨国公司在华研发战略的广泛讨论。这一决定不仅影响了众多IT从业者的职业发展&#xff0c;也让人思考全球化背景下中国IT产业的竞争力和未来发展方向。面对…

手机、平板电脑编程———未来之窗行业应用跨平台架构

一、平板编程优点 1. 便携性强 - 可以随时随地携带平板进行编程&#xff0c;不受地点限制&#xff0c;方便在旅行、出差或休息时间进行学习和开发。 2. 直观的触摸操作 - 利用触摸屏幕进行代码编辑、缩放、拖动等操作&#xff0c;提供了一种直观和自然的交互方式。 …

TypeScript:高级类型

一、交叉类型&#xff08;Intersection Types&#xff09; 交叉类型是将多个类型合并为一个类型。 这让我们可以把现有的多种类型叠加到一起成为一种类型&#xff0c;它包含了所需的所有类型的特性。 例如&#xff0c; Person & Serializable & Loggable同时是 Person …

建模杂谈系列256 规则函数化改造

说明 之前尝试用FastAPI来构造规则&#xff0c;碰到的问题是由于请求量过大(TPS > 1000), 从而导致微服务端口资源耗尽。所以现在的point是: 1 如何使用函数来替代微服务(同时要保留使用微服务的优点)2 进一步抽象并规范规则的执行3 等效合并规则的方法 内容 0 机制讨论…

Vue2源码解读

vue源码_哔哩哔哩_bilibili 1.Vue源码路径目录解读 Vue2源码的路径目录被设计得非常清晰&#xff0c;每个文件夹都承担着特定的职责和功能。以下是这些主要文件夹&#xff08;compiler、core、platform、server、sfc、shared&#xff09;的详细解读&#xff1a; 1. compiler …

LLM大模型部署实战指南:Ollama简化流程,OpenLLM灵活部署,LocalAI本地优化,Dify赋能应用开发

1. Ollama 部署的本地模型(&#x1f53a;) Ollama 是一个开源框架&#xff0c;专为在本地机器上便捷部署和运行大型语言模型&#xff08;LLM&#xff09;而设计。&#xff0c;这是 Ollama 的官网地址&#xff1a;https://ollama.com/ 以下是其主要特点和功能概述&#xff1a; …

VLMEvalKit 评测实践:InternVL2 VS Qwen2VL

一、InternVL2简介 InternVL2是由上海人工智能实验室OpenGVLab发布的一款多模态大模型&#xff0c;其中文名称为“书生万象”。该模型在多学科问答&#xff08;MMMU&#xff09;任务上表现出色&#xff0c;成为国内首个在该任务上性能突破60的模型&#xff0c;被誉为开源多模态…

k8s 微服务 ingress-nginx 金丝雀发布

目录 一 什么是微服务 二 微服务的类型 三 ipvs模式 3.1 ipvs模式配置方式 四 微服务类型详解 4.1 clusterip 4.2 ClusterIP中的特殊模式headless 4.3 nodeport 4.4 loadbalancer 4.5 metalLB 4.6 externalname 五 Ingress-nginx 5.1 ingress-nginx功能 5.2 部署…

5. Python之数据类型

Python数据类型有数值型&#xff0c;字符串型&#xff0c;布尔型等等 内置函数type()&#xff0c;可以查看变量的数据类型 。 一、数值类型 整数&#xff08;没有小数部分&#xff0c;包含正整数&#xff0c;负整数&#xff0c;0&#xff0c;默认为十进制数&#xff09;&…

C++ 类域+类的对象大小

个人主页&#xff1a;Jason_from_China-CSDN博客 所属栏目&#xff1a;C系统性学习_Jason_from_China的博客-CSDN博客 所属栏目&#xff1a;C知识点的补充_Jason_from_China的博客-CSDN博客 概念概述 类定义了一个新的作用域&#xff0c;类的所有成员都在类的作用域中&#xff…