前言
在wasmer-java导入函数中提到wasm操作限制较大。我们需要通过导入外部函数去解决一些问题。
截至写文章时,已用wasmer-java中他人维护的分支解决导入函数问题
问题
但是导入的外部函数与wasm(实际上为rust程序)之间参数传递只能使用int, long ,float, double 四种,这是远远不够的。
解决方法
对于一些复杂对象的传递,我们可以考虑使用字符串。但是字符串类型也是不能作为参数直接在Java与wasm中直接传递的,我们需要借助wasmer-java中的Memory类,将字符串直接写入虚拟机内存中,并传递一个 int 类型的指针。
传入字符串
Java
参数初始化
1 2 3 4 5 6 7 8 9 10 11
| Memory memory = instance.exports.getMemory("memory"); String str = "要传递的参数";
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
Integer strPtr = (Integer) instance.exports.getFunction("allocate").apply(bytes.length)[0];
ByteBuffer mbf = memory.buffer(); mbf.position(strPtr); mbf.put(bytes);
|
参数传递
1
| Object[] results = instance.exports.getFunction("函数名").apply(strPtr);
|
Rust
直接解析
通过CStr和CString两个库操作
1 2 3 4 5 6 7 8 9 10
| #[no_mangle] pub extern fn func(param_ptr: *mut c_char){ let result; unsafe { result = CStr::from_ptr(str_ptr).to_str().unwrap(); }
let string = CString::new(format!("wallet:{}", result)).unwrap(); }
|
传出字符串
Rust
返回 *mut c_char 类型即可
1 2 3 4 5 6 7 8
| #[no_mangle] pub extern fn func() -> *mut c_char{ let result = ...; let string = CString::new(format!("wallet:{}", result)).unwrap(); string.into_raw() }
|
Java
1 2 3 4 5 6 7
| Integer resultPtr = (Integer) instance.exports.getFunction("func").apply()[0];
Memory memory = instance.exports.getMemory("memory"); ByteBuffer mbf = memory.buffer();
String res = getString(resultPtr,mbf);
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| public static String getString(Integer ptr, ByteBuffer mbf) { StringBuilder sb = new StringBuilder(); for(int i = ptr, max = mbf.limit(); i < max; i++) { mbf.position(i); byte b = mbf.get(); if (b == 0) { break; } sb.appendCodePoint(b); } String result = sb.toString(); return result; }
|