操作系统: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连接,还有跨域限制,不知道能不能连接上别的端口,不是本地端口的话可能会被限制。