自定义外部引用

外部引用指示对 host 对象的不透明且不可伪造的引用。新的 externref 类型可以被传递到 Wasm 模块或从 Wasm 模块返回。Wasm 模块不能显示 externref 值的位模式,也不能通过整数值创建一个假的 host 引用。

教程

下面的教程是对 WasmEdge 中的 externref 示例的总结。

准备 Wasm 文件

Wasm 文件应该包含接受 externref 的 host 函数导入。以这个 WASM 测试用例为例(WAT是相对应的文本格式)。

  1. (module
  2. (type $t0 (func (param externref i32) (result i32)))
  3. (type $t1 (func (param externref i32 i32) (result i32)))
  4. (type $t2 (func (param externref externref i32 i32) (result i32)))
  5. (import "extern_module" "functor_square" (func $functor_square (type $t0)))
  6. (import "extern_module" "class_add" (func $class_add (type $t1)))
  7. (import "extern_module" "func_mul" (func $func_mul (type $t1)))
  8. (func $call_add (export "call_add") (type $t1) (param $p0 externref) (param $p1 i32) (param $p2 i32) (result i32)
  9. (call $class_add
  10. (local.get $p0)
  11. (local.get $p1)
  12. (local.get $p2)))
  13. (func $call_mul (export "call_mul") (type $t1) (param $p0 externref) (param $p1 i32) (param $p2 i32) (result i32)
  14. (call $func_mul
  15. (local.get $p0)
  16. (local.get $p1)
  17. (local.get $p2)))
  18. (func $call_square (export "call_square") (type $t0) (param $p0 externref) (param $p1 i32) (result i32)
  19. (call $functor_square
  20. (local.get $p0)
  21. (local.get $p1)))
  22. (func $call_add_square (export "call_add_square") (type $t2) (param $p0 externref) (param $p1 externref) (param $p2 i32) (param $p3 i32) (result i32)
  23. (call $functor_square
  24. (local.get $p1)
  25. (call $class_add
  26. (local.get $p0)
  27. (local.get $p2)
  28. (local.get $p3))))
  29. (memory $memory (export "memory") 1))

你可以通过 wat2wasm 在线实时工具将 wat 转换为 wasm。注意页面上的 reference types 复选框必须勾选。

实现 Host 模块以及在 WasmEdge 中注册

在执行 Wasm 执行前,host 模块必须实现以及在 WasmEdge 中注册。假设下面的代码保存为 main.c

  1. #include <wasmedge/wasmedge.h>
  2. #include <stdio.h>
  3. uint32_t SquareFunc(uint32_t A) { return A * A; }
  4. uint32_t AddFunc(uint32_t A, uint32_t B) { return A + B; }
  5. uint32_t MulFunc(uint32_t A, uint32_t B) { return A * B; }
  6. // Host 函数通过外部引用调用 `SquareFunc`
  7. WasmEdge_Result ExternSquare(void *Data, WasmEdge_MemoryInstanceContext *MemCxt,
  8. const WasmEdge_Value *In, WasmEdge_Value *Out) {
  9. // 函数类型: {externref, i32} -> {i32}
  10. uint32_t (*Func)(uint32_t) = WasmEdge_ValueGetExternRef(In[0]);
  11. uint32_t C = Func(WasmEdge_ValueGetI32(In[1]));
  12. Out[0] = WasmEdge_ValueGenI32(C);
  13. return WasmEdge_Result_Success;
  14. }
  15. // Host 函数通过外部引用调用 `AddFunc`
  16. WasmEdge_Result ExternAdd(void *Data, WasmEdge_MemoryInstanceContext *MemCxt,
  17. const WasmEdge_Value *In, WasmEdge_Value *Out) {
  18. // 函数类型: {externref, i32, i32} -> {i32}
  19. uint32_t (*Func)(uint32_t, uint32_t) = WasmEdge_ValueGetExternRef(In[0]);
  20. uint32_t C = Func(WasmEdge_ValueGetI32(In[1]), WasmEdge_ValueGetI32(In[2]));
  21. Out[0] = WasmEdge_ValueGenI32(C);
  22. return WasmEdge_Result_Success;
  23. }
  24. // host 函数通过外部引用调用 `ExternMul`
  25. WasmEdge_Result ExternMul(void *Data, WasmEdge_MemoryInstanceContext *MemCxt,
  26. const WasmEdge_Value *In, WasmEdge_Value *Out) {
  27. // 函数类型: {externref, i32, i32} -> {i32}
  28. uint32_t (*Func)(uint32_t, uint32_t) = WasmEdge_ValueGetExternRef(In[0]);
  29. uint32_t C = Func(WasmEdge_ValueGetI32(In[1]), WasmEdge_ValueGetI32(In[2]));
  30. Out[0] = WasmEdge_ValueGenI32(C);
  31. return WasmEdge_Result_Success;
  32. }
  33. // 创建“extern_module”引入对象的辅助函数。
  34. WasmEdge_ImportObjectContext *CreateExternModule() {
  35. WasmEdge_String HostName;
  36. WasmEdge_FunctionTypeContext *HostFType = NULL;
  37. WasmEdge_FunctionInstanceContext *HostFunc = NULL;
  38. enum WasmEdge_ValType P[3], R[1];
  39. HostName = WasmEdge_StringCreateByCString("extern_module");
  40. WasmEdge_ImportObjectContext *ImpObj = WasmEdge_ImportObjectCreate(HostName);
  41. WasmEdge_StringDelete(HostName);
  42. // 添加 host 函数 "functor_square": {externref, i32} -> {i32}
  43. P[0] = WasmEdge_ValType_ExternRef;
  44. P[1] = WasmEdge_ValType_I32;
  45. R[0] = WasmEdge_ValType_I32;
  46. HostFType = WasmEdge_FunctionTypeCreate(P, 2, R, 1);
  47. HostFunc = WasmEdge_FunctionInstanceCreate(HostFType, ExternSquare, NULL, 0);
  48. WasmEdge_FunctionTypeDelete(HostFType);
  49. HostName = WasmEdge_StringCreateByCString("functor_square");
  50. WasmEdge_ImportObjectAddFunction(ImpObj, HostName, HostFunc);
  51. WasmEdge_StringDelete(HostName);
  52. // 添加 host 函数 "class_add": {externref, i32, i32} -> {i32}
  53. P[2] = WasmEdge_ValType_I32;
  54. HostFType = WasmEdge_FunctionTypeCreate(P, 3, R, 1);
  55. HostFunc = WasmEdge_FunctionInstanceCreate(HostFType, ExternAdd, NULL, 0);
  56. WasmEdge_FunctionTypeDelete(HostFType);
  57. HostName = WasmEdge_StringCreateByCString("class_add");
  58. WasmEdge_ImportObjectAddFunction(ImpObj, HostName, HostFunc);
  59. WasmEdge_StringDelete(HostName);
  60. // 添加 host 函数 "func_mul": {externref, i32, i32} -> {i32}
  61. HostFType = WasmEdge_FunctionTypeCreate(P, 3, R, 1);
  62. HostFunc = WasmEdge_FunctionInstanceCreate(HostFType, ExternMul, NULL, 0);
  63. WasmEdge_FunctionTypeDelete(HostFType);
  64. HostName = WasmEdge_StringCreateByCString("func_mul");
  65. WasmEdge_ImportObjectAddFunction(ImpObj, HostName, HostFunc);
  66. WasmEdge_StringDelete(HostName);
  67. return ImpObj;
  68. }
  69. int main() {
  70. WasmEdge_VMContext *VMCxt = WasmEdge_VMCreate(NULL, NULL);
  71. WasmEdge_ImportObjectContext *ImpObj = CreateExternModule();
  72. WasmEdge_Value P[3], R[1];
  73. WasmEdge_String FuncName;
  74. WasmEdge_Result Res;
  75. Res = WasmEdge_VMRegisterModuleFromImport(VMCxt, ImpObj);
  76. if (!WasmEdge_ResultOK(Res)) {
  77. printf("Import object registration failed\n");
  78. return EXIT_FAILURE;
  79. }
  80. Res = WasmEdge_VMLoadWasmFromFile(VMCxt, "funcs.wasm");
  81. if (!WasmEdge_ResultOK(Res)) {
  82. printf("WASM file loading failed\n");
  83. return EXIT_FAILURE;
  84. }
  85. Res = WasmEdge_VMValidate(VMCxt);
  86. if (!WasmEdge_ResultOK(Res)) {
  87. printf("WASM validation failed\n");
  88. return EXIT_FAILURE;
  89. }
  90. Res = WasmEdge_VMInstantiate(VMCxt);
  91. if (!WasmEdge_ResultOK(Res)) {
  92. printf("WASM instantiation failed\n");
  93. return EXIT_FAILURE;
  94. }
  95. // 测试用例 1:调用 add -- 1234 + 5678
  96. P[0] = WasmEdge_ValueGenExternRef(AddFunc);
  97. P[1] = WasmEdge_ValueGenI32(1234);
  98. P[2] = WasmEdge_ValueGenI32(5678);
  99. FuncName = WasmEdge_StringCreateByCString("call_add");
  100. Res = WasmEdge_VMExecute(VMCxt, FuncName, P, 3, R, 1);
  101. WasmEdge_StringDelete(FuncName);
  102. if (WasmEdge_ResultOK(Res)) {
  103. printf("Test 1 -- `call_add` -- 1234 + 5678 = %d\n",
  104. WasmEdge_ValueGetI32(R[0]));
  105. } else {
  106. printf("Test 1 -- `call_add` -- 1234 + 5678 -- failed\n");
  107. return EXIT_FAILURE;
  108. }
  109. // 测试用例 2:调用 mul -- 789 * 4321
  110. P[0] = WasmEdge_ValueGenExternRef(MulFunc);
  111. P[1] = WasmEdge_ValueGenI32(789);
  112. P[2] = WasmEdge_ValueGenI32(4321);
  113. FuncName = WasmEdge_StringCreateByCString("call_mul");
  114. Res = WasmEdge_VMExecute(VMCxt, FuncName, P, 3, R, 1);
  115. WasmEdge_StringDelete(FuncName);
  116. if (WasmEdge_ResultOK(Res)) {
  117. printf("Test 2 -- `call_mul` -- 789 * 4321 = %d\n",
  118. WasmEdge_ValueGetI32(R[0]));
  119. } else {
  120. printf("Test 2 -- `call_mul` -- 789 * 4321 -- failed\n");
  121. return EXIT_FAILURE;
  122. }
  123. // 测试用例 3:调用 square -- 8256^2
  124. P[0] = WasmEdge_ValueGenExternRef(SquareFunc);
  125. P[1] = WasmEdge_ValueGenI32(8256);
  126. FuncName = WasmEdge_StringCreateByCString("call_square");
  127. Res = WasmEdge_VMExecute(VMCxt, FuncName, P, 2, R, 1);
  128. if (WasmEdge_ResultOK(Res)) {
  129. printf("Test 3 -- `call_mul` -- 8256 ^ 2 = %d\n",
  130. WasmEdge_ValueGetI32(R[0]));
  131. } else {
  132. printf("Test 3 -- `call_mul` -- 8256 ^ 2 -- failed\n");
  133. return EXIT_FAILURE;
  134. }
  135. return EXIT_SUCCESS;
  136. }

设置环境并编译

  1. 安装 WasmEdge 共享库。

    详细信息请参阅安装

  2. 如上所示准备 WASM 文件和 main.c 源文件。

  3. 编译

    1. gcc main.c -lwasmedge_c
    2. # 或者你可以在 C++ 场景下使用 g++,或者使用 clang。
  4. 运行测试用例

    1. $ ./a.out
    2. Test 1 -- `call_add` -- 1234 + 5678 = 6912
    3. Test 2 -- `call_mul` -- 789 * 4321 = 3409269
    4. Test 3 -- `call_mul` -- 8256 ^ 2 = 68161536

使用外部引用的 Wasm

以下文的 wat 为例:

  1. (module
  2. (type $t0 (func (param externref i32) (result i32)))
  3. ;; Import a host function which type is {externref i32} -> {i32}
  4. (import "extern_module" "functor_square" (func $functor_square (type $t0)))
  5. ;; Wasm function which type is {externref i32} -> {i32} and exported as "call_square"
  6. (func $call_square (export "call_square") (type $t0) (param $p0 externref) (param $p1 i32) (result i32)
  7. (call $functor_square (local.get $p0) (local.get $p1))
  8. )
  9. (memory $memory (export "memory") 1))

Wasm 函数 “call_square“ 包含一个 externref 参数,并用这个 externref 调用导入的 host 函数 functor_square。所以,当你调用 Wasm 函数 call_square 并传递对象的引用时,host 函数 functor_square 就能获得该对应引用。

WasmEdge ExternRef 示例

下面的例子展示了如何在 Wasm 里通过 WasmEdge C API 使用 externref

Wasm 代码

Wasm 代码必须将 externref 传递给想要访问它的 host 函数。以下文的 wat 为例,这是 WASM 测试用例的其中一部分:

  1. (module
  2. (type $t0 (func (param externref i32 i32) (result i32)))
  3. (import "extern_module" "func_mul" (func $func_mul (type $t0)))
  4. (func $call_mul (export "call_mul") (type $t0) (param $p0 externref) (param $p1 i32) (param $p2 i32) (result i32)
  5. (call $func_mul (local.get $p0) (local.get $p1) (local.get $p2))
  6. )
  7. (memory $memory (export "memory") 1))

host 函数 extern_module::func_mulexternref 作为一个函数指针用来将参数 1 和参数 2 相乘并返回其结果。输出的 Wasm 函数 call_mul 调用 func_mul 并传递 externref 和 2 个数字作为参数。

Host 函数

要实例化上面的 Wasm 示例,host 函数必须注册到 WasmEdge 中。详见 Host 函数。接受 externref 的 host 函数必须知道原始对象的类型。我们以函数指针为例。

  1. /* 作为函数指针传递的函数。 */
  2. uint32_t MulFunc(uint32_t A, uint32_t B) { return A * B; }
  3. /* Host 函数通过外部引用作为函数指针来调用函数 */
  4. WasmEdge_Result ExternMul(void *, WasmEdge_MemoryInstanceContext *,
  5. const WasmEdge_Value *In, WasmEdge_Value *Out) {
  6. /* 函数类型: {externref, i32, i32} -> {i32} */
  7. void *Ptr = WasmEdge_ValueGetExternRef(In[0]);
  8. uint32_t (*Obj)(uint32_t, uint32_t) = Ptr;
  9. /*
  10. * 对于 C++ 来说,`reinterpret_cast` 是必需的:
  11. * uint32_t (*Obj)(uint32_t, uint32_t) =
  12. * *reinterpret_cast<uint32_t (*)(uint32_t, uint32_t)>(Ptr);
  13. */
  14. uint32_t C = Obj(WasmEdge_ValueGetI32(In[1]), WasmEdge_ValueGetI32(In[2]));
  15. Out[0] = WasmEdge_ValueGenI32(C);
  16. return WasmEdge_Result_Success;
  17. }

MulFunc“ 是一个函数,将作为 externref 传递给 Wasm。在 host 函数 “func_mul“ 中,你可以使用 “WasmEdge_ValueGetExternRef“ API 从包含 externrefWasmEdge_Value 中获取指针。

开发人员可以将带有名称的 host 函数添加到导入对象中。

  1. /* 创建一个导入对象。 */
  2. WasmEdge_String HostName = WasmEdge_StringCreateByCString("extern_module");
  3. WasmEdge_ImportObjectContext *ImpObj = WasmEdge_ImportObjectCreate(HostName);
  4. WasmEdge_StringDelete(HostName);
  5. /* 创建一个函数实例并添加到一个导入对象中。 */
  6. enum WasmEdge_ValType P[3], R[1];
  7. P[0] = WasmEdge_ValType_ExternRef;
  8. P[1] = WasmEdge_ValType_I32;
  9. P[2] = WasmEdge_ValType_I32;
  10. R[0] = WasmEdge_ValType_I32;
  11. WasmEdge_FunctionTypeContext *HostFType = WasmEdge_FunctionTypeCreate(P, 3, R, 1);
  12. WasmEdge_FunctionInstanceContext *HostFunc = WasmEdge_FunctionInstanceCreate(HostFType, ExternFuncMul, NULL, 0);
  13. WasmEdge_FunctionTypeDelete(HostFType);
  14. HostName = WasmEdge_StringCreateByCString("func_mul");
  15. WasmEdge_ImportObjectAddFunction(ImpObj, HostName, HostFunc);
  16. WasmEdge_StringDelete(HostName);
  17. ...

执行

这个 WASM 测试用例为例(WAT是相对应的文本格式)。假设函数 funcs.wasm 被复制到了当前目录。下面的例子展示了如何在 Wasm 里用 WasmEdge C API 使用 externref

  1. /* 创建 VM 上下文。 */
  2. WasmEdge_VMContext *VMCxt = WasmEdge_VMCreate(NULL, NULL);
  3. /* 创建包含 host 函数的导入对象上下文。 */
  4. WasmEdge_ImportObjectContext *ImpObj = /* Ignored ... */;
  5. /* 假设 host 函数被添加到上面的导入对象中。 */
  6. WasmEdge_Value P[3], R[1];
  7. WasmEdge_String FuncName;
  8. WasmEdge_Result Res;
  9. /* 将导入对象注册到 VM。 */
  10. Res = WasmEdge_VMRegisterModuleFromImport(VMCxt, ImpObj);
  11. if (!WasmEdge_ResultOK(Res)) {
  12. printf("Import object registration failed\n");
  13. return EXIT_FAILURE;
  14. }
  15. /* 从文件中加载 WASM。 */
  16. Res = WasmEdge_VMLoadWasmFromFile(VMCxt, "funcs.wasm");
  17. if (!WasmEdge_ResultOK(Res)) {
  18. printf("WASM file loading failed\n");
  19. return EXIT_FAILURE;
  20. }
  21. /* 验证 WASM。 */
  22. Res = WasmEdge_VMValidate(VMCxt);
  23. if (!WasmEdge_ResultOK(Res)) {
  24. printf("WASM validation failed\n");
  25. return EXIT_FAILURE;
  26. }
  27. /* 实例化 WASM 模块。 */
  28. Res = WasmEdge_VMInstantiate(VMCxt);
  29. if (!WasmEdge_ResultOK(Res)) {
  30. printf("WASM instantiation failed\n");
  31. return EXIT_FAILURE;
  32. }
  33. /* 运行 WASM 函数。 */
  34. P[0] = WasmEdge_ValueGenExternRef(AddFunc);
  35. P[1] = WasmEdge_ValueGenI32(1234);
  36. P[2] = WasmEdge_ValueGenI32(5678);
  37. /* 运行 `call_add` 函数。 */
  38. FuncName = WasmEdge_StringCreateByCString("call_add");
  39. Res = WasmEdge_VMExecute(VMCxt, FuncName, P, 3, R, 1);
  40. WasmEdge_StringDelete(FuncName);
  41. if (WasmEdge_ResultOK(Res)) {
  42. printf("Run -- `call_add` -- 1234 + 5678 = %d\n",
  43. WasmEdge_ValueGetI32(R[0]));
  44. } else {
  45. printf("Run -- `call_add` -- 1234 + 5678 -- failed\n");
  46. return EXIT_FAILURE;
  47. }

传递对象

上面的例子是传递一个函数引用 externref。下面的例子是关于如何在 C++ 中将对象引用作为 externref 传递给 WASM 的。

传递一个类

将一个类通过 externref 传递,对象实例是必须的。

  1. class AddClass {
  2. public:
  3. uint32_t add(uint32_t A, uint32_t B) const { return A + B; }
  4. };
  5. AddClass AC;

然后你可以通过使用 WasmEdge_ValueGenExternRef() API 将对象传入 WasmEdge。

  1. WasmEdge_Value P[3], R[1];
  2. P[0] = WasmEdge_ValueGenExternRef(&AC);
  3. P[1] = WasmEdge_ValueGenI32(1234);
  4. P[2] = WasmEdge_ValueGenI32(5678);
  5. WasmEdge_String FuncName = WasmEdge_StringCreateByCString("call_add");
  6. WasmEdge_Result Res = WasmEdge_VMExecute(VMCxt, FuncName, P, 3, R, 1);
  7. WasmEdge_StringDelete(FuncName);
  8. if (WasmEdge_ResultOK(Res)) {
  9. std::cout << "Result : " << WasmEdge_ValueGetI32(R[0]) std::endl;
  10. // 将会打印 `6912`.
  11. } else {
  12. return EXIT_FAILURE;
  13. }

在通过引用访问对象的 host 函数中,你可以使用 WasmEdge_ValueGetExternRef() API 来检索对对象的引用。

  1. // 修改上面的教程中的 `ExternAdd`。
  2. WasmEdge_Result ExternAdd(void *, WasmEdge_MemoryInstanceContext *,
  3. const WasmEdge_Value *In, WasmEdge_Value *Out) {
  4. // 函数类型:{externref, i32, i32} -> {i32}
  5. void *Ptr = WasmEdge_ValueGetExternRef(In[0]);
  6. AddClass &Obj = *reinterpret_cast<AddClass *>(Ptr);
  7. uint32_t C =
  8. Obj.add(WasmEdge_ValueGetI32(In[1]), WasmEdge_ValueGetI32(In[2]));
  9. Out[0] = WasmEdge_ValueGenI32(C);
  10. return WasmEdge_Result_Success;
  11. }

传递一个对象作为仿函数

与传递类实例一样,需要 functor 对象实例。

  1. struct SquareStruct {
  2. uint32_t operator()(uint32_t Val) const { return Val * Val; }
  3. };
  4. SquareStruct SS;

然后你可以通过使用 WasmEdge_ValueGenExternRef() API 将对象传递到 WasmEdge。

  1. WasmEdge_Value P[2], R[1];
  2. P[0] = WasmEdge_ValueGenExternRef(&SS);
  3. P[1] = WasmEdge_ValueGenI32(1024);
  4. WasmEdge_String FuncName = WasmEdge_StringCreateByCString("call_square");
  5. WasmEdge_Result Res = WasmEdge_VMExecute(VMCxt, FuncName, P, 2, R, 1);
  6. WasmEdge_StringDelete(FuncName);
  7. if (WasmEdge_ResultOK(Res)) {
  8. std::cout << "Result : " << WasmEdge_ValueGetI32(R[0]) std::endl;
  9. // 将会打印 `1048576`.
  10. } else {
  11. return EXIT_FAILURE;
  12. }

在通过引用访问对象的 host 函数中,你可以使用 WasmEdge_ValueGetExternRef API 来检索对该对象的引用,而该引用是一个 functor。

  1. // 修改上文教程中的 `ExternSquare`。
  2. WasmEdge_Result ExternSquare(void *, WasmEdge_MemoryInstanceContext *,
  3. const WasmEdge_Value *In, WasmEdge_Value *Out) {
  4. // 函数类型:{externref, i32, i32} -> {i32}
  5. void *Ptr = WasmEdge_ValueGetExternRef(In[0]);
  6. SquareStruct &Obj = *reinterpret_cast<SquareStruct *>(Ptr);
  7. uint32_t C = Obj(WasmEdge_ValueGetI32(In[1]));
  8. Out[0] = WasmEdge_ValueGenI32(C);
  9. return WasmEdge_Result_Success;
  10. }

传递 STL 对象

example Wasm binary 提供了与 host 函数交互的函数可以访问 C++ STL 对象的示例(WAT 是相对应的文本格式)。

假设 WASM 文件 stl.wasm 被复制到了当前目录。

以下文的 std::ostreamstd::string 为例。假设有一个 host 函数可以通过 externref 访问 std::ostreamstd::string

  1. // Host 函数,通过 std::ostream 输出 std::string
  2. WasmEdge_Result ExternSTLOStreamStr(void *, WasmEdge_MemoryInstanceContext *,
  3. const WasmEdge_Value *In,
  4. WasmEdge_Value *) {
  5. // 函数类型:{externref, externref} -> {}
  6. void *Ptr0 = WasmEdge_ValueGetExternRef(In[0]);
  7. void *Ptr1 = WasmEdge_ValueGetExternRef(In[1]);
  8. std::ostream &RefOS = *reinterpret_cast<std::ostream *>(Ptr0);
  9. std::string &RefStr = *reinterpret_cast<std::string *>(Ptr1);
  10. RefOS << RefStr;
  11. return WasmEdge_Result_Success;
  12. }

假设上面的 host 函数被添加到一个导入对象 ImpObj 中,并且 ImpObj 被注册到一个虚拟机上下文 VMCxt 中。然后你可以通过以下代码实例化 Wasm 模块:

  1. WasmEdge_Result Res = WasmEdge_VMLoadWasmFromFile(VMCxt, "stl.wasm");
  2. if (!WasmEdge_ResultOK(Res)) {
  3. printf("WASM file loading failed\n");
  4. return EXIT_FAILURE;
  5. }
  6. Res = WasmEdge_VMValidate(VMCxt);
  7. if (!WasmEdge_ResultOK(Res)) {
  8. printf("WASM validation failed\n");
  9. return EXIT_FAILURE;
  10. }
  11. Res = WasmEdge_VMInstantiate(VMCxt);
  12. if (!WasmEdge_ResultOK(Res)) {
  13. printf("WASM instantiation failed\n");
  14. return EXIT_FAILURE;
  15. }

最后,通过外部引用传递 std::coutstd::string 对象。

  1. std::string PrintStr("Hello world!");
  2. WasmEdge_Value P[2], R[1];
  3. P[0] = WasmEdge_ValueGenExternRef(&std::cout);
  4. P[1] = WasmEdge_ValueGenExternRef(&PrintStr);
  5. WasmEdge_String FuncName = WasmEdge_StringCreateByCString("call_ostream_str");
  6. WasmEdge_Result Res = WasmEdge_VMExecute(VMCxt, FuncName, P, 2, R, 1);
  7. // 将会打印 "Hello world!" 到标准输出 stdout.
  8. WasmEdge_StringDelete(FuncName);
  9. if (!WasmEdge_ResultOK(Res)) {
  10. return EXIT_FAILURE;
  11. }

对于其它 C++ STL 对象的情况,例如 std::vector<T>std::map<T, U>std::set<T>,如果 reinterpret_cast 中的类型是正确的,该对象就可以在 host 函数中被正确访问到。