WebAssembly中C++和JS之间的字符串传递和简单替换加密

操作系统:ubuntu 22.04(没错就是这个狗东西,一大堆新bug产生地)

使用语言:C++14,html(自学一下,主要是会script部分)

使用编译器:gcc,g++,emcc(这个找教程自己装),cmake

使用IDE:Clion2018.3

浏览器:建议使用火狐或者谷歌

废话不多说,直接上代码~

main.cpp

#include <stdio.h>
#include <iostream>
#include <emscripten.h>
#include <stdlib.h>
#include <string.h>
#include <cstring>

#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

//autor:cxx
//测试运行
EM_PORT_API(void) test()
{
    std::cout<<"hello world!"<<std::endl;
}

//测试1
EM_PORT_API(char*) outName(char *n)
{
    char xhName[] = "xuanhun";
    strcat(n, xhName);
    return n;
}
//KS加密
EM_PORT_API(char*) ksencry(char *c,int n)
{
    char res[]="";
    for(int i=0;i<=strlen(c)-1;i++) {
        c[i] = c[i] + n % 26;
        if (c[i] > 'z') n -= 26;
    }

    strcat(res,c);
    return res;
}

//KS解密
EM_PORT_API(char*) ksdecry(char *c,int n)
{
    char res[]="";
    for(int i=0;i<=strlen(c)-1;i++) {
        c[i] = c[i] - n % 26;
        if (c[i] > 'z') n -= 26;
    }

    strcat(res,c);
    return res;
}

//其他测试方案...

这里解释一下开头的一大堆引用和宏,就是为了在JS中可以使用C或者C++函数所先要指定的,另外,头文件emscripten.h需要自己在安装emsdk时引用绝对路径导入cmakelist.txt里面,不然会无法使用部分函数。这里写的加解密函数只是很简单的用于测试的凯撒密码,但是可以替换成其他的高大上密码啥的,比如AES和RSA之类的需要生成密钥的密码。

写好C++文件后,需要进行编译,编译语句如下:

emcc main.cpp -o ./build/forUpdate.js -s EXPORTED_FUNCTIONS="['_malloc','_free']" -s WASM=1

在build文件夹中产生两个文件forUpdate.js和forUpdate.wasm,其中前者将会被引用。

创建文件forUpdate.html,在里面写入样式和转换代码。

forUpdate.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ForUpdateTest</title>
</head>
<body>
<script>
    function f1(k,b) {

        var ptr =allocate(intArrayFromString(k),ALLOC_NORMAL);

        var resP=_ksencry(ptr,b);

        console.log("KS加密结果"+UTF8ToString(resP));

        document.getElementById("textshow").value += "KS加密结果:"+UTF8ToString(resP)+ "\n\r";

        return UTF8ToString(resP);

        _free(ptr);
    }

    function f2(k,b) {

        var ptr =allocate(intArrayFromString(k),ALLOC_NORMAL);

        var resP=_ksdecry(ptr,b);

        console.log("KS解密结果"+UTF8ToString(resP));

        document.getElementById("textshow").value += "KS解密结果:"+UTF8ToString(resP)+"\n\r";

        _free(ptr);
    }

    function f3() {
        var msg =document.getElementById('input').value;

        console.log('获取到字符串:'+msg);

        document.getElementById("textshow").value += '获取到字符串:'+msg + "\n\r";

        return msg;
    }

    function f4()
    {
        var msg =document.getElementById('bit').value;

        console.log('获取到替换位数:'+msg);

        document.getElementById("textshow").value += '获取到替换位数:'+msg +"\n\r";

        return msg;
    }

    function f5() {

        document.getElementById("textshow").value ="";

        console.log("清空文本域");
    }

</script>

<script async type="text/javascript" src="build/forUpdate.js"></script>

<div>请在输入框里输入需要加密的字符串和替换位数!</div>
<br/>
<form>

    <input type="text" id ="input" placeholder="请输入字符串" maxlength="20"/>
    <input type="text" id ="bit" placeholder="请输入替换位数" maxlength="20"/>

</form>


<br/>
<input type="button" value="KS加密" onclick="f1(f3(),f4())" />
<input type="button" value="KS解密" onclick="f2(f1(f3(),f4()),f4())" />
<br/>
<br/>


<form>
    结果展示:<textarea name="description" id="textshow" cols="30" rows="6" placeholder="过程"> </textarea>
    <input type="button" value="清空" onclick="f5()" />
</form>


</body>
</html>

allocate开辟指针的空间,这一步很重要。这一步有可能需要在导出函数那里写上,我的emcc不需要,要写上就这么写,还可以写上自己想导出的其他函数,具体可以自己搜搜。

emcc main.cpp -o ./build/forUpdate.js -s EXPORTED_FUNCTIONS="['_malloc','_free','allocate']" -s WASM=1

其他就是很简单的控件值的取用,可以在控制台查看,也可以在文本域里查看,这里是把所有的步骤语句都打印出来的,可以修改。

基本结果展示:

 

大功告成,原来直接传值都是输出UTF-8的地址编码,人都快死了。后来发现需要用指针承接,再使用转换函数,才能正常输出。

碎碎念

下周想试试能不能通过写C++发邮件函数,再引用编译过的JS文件实现在前端发邮件?尝试一下吧,毕竟好像从理论上来说可以一试,不过WebAssembly只支持http和websocket连接,还有跨域限制,不知道能不能连接上别的端口,不是本地端口的话可能会被限制。

猜你喜欢

转载自blog.csdn.net/daxuanzi515/article/details/125966697
今日推荐