Stream: git-wasmtime

Topic: wasmtime / Issue #2646 Access to callbacks exported by Wa...


view this post on Zulip Wasmtime GitHub notifications bot (Feb 08 2021 at 18:00):

sergiizubchevskyy opened Issue #2646:

Hello!

I'm currently embedding the Wasmtime in the C/C++ and got an issue with the callbacks.

What I'm trying to achieve is to call a function, exported by the WASM script, from within the host system.

Here is the example:

![image](https://user-images.githubusercontent.com/44066210/107259486-f2d7ba80-6a34-11eb-8e60-207584a0009b.png)

From the host side, when conditions occur, I want to call the onTimer1 function.

This generates the following WASM code:

![image](https://user-images.githubusercontent.com/44066210/107259537-03883080-6a35-11eb-92df-8f1f5234b75a.png)

Now from the C/C++ host, I get the following exports:

![image](https://user-images.githubusercontent.com/44066210/107259689-36cabf80-6a35-11eb-9a3d-bec21ebf8153.png)

My issue is that when the script invokes the function "startTimer" in the callback parameter I get 1 (integer value of one). And if I try to get the callback with the 'wasm_extern_as_func' function it will misbehave because the index of the exported function in the exports is 2, not 1. If I hardcode the index of 2 it will work as expected.

I assumed that there is a need to create a table but I tried creating it using 'memory' (exports index 0) and '__table_base' (exports index 11), but the created table is always NULL (the module and exports are correct).

After I took a look at some examples I came to the conclusion that the only way to call a function is to know exactly the index of it in the exports, which can be found if I know the name of the function. For example (taken from https://github.com/WebAssembly/wasm-c-api/blob/master/example/table.c):
![image](https://user-images.githubusercontent.com/44066210/107260692-4a2a5a80-6a36-11eb-9e42-32ac440be6d7.png)

Am I missing something? Is the only way to get the function is to know the index of it in the exports? Is there a way to get a function via WASM table or something similar by using the value provided when the startTimer function is called?

Thank you in advance and sorry for the long post.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 08 2021 at 19:46):

alexcrichton commented on Issue #2646:

Thanks for the report! There's a number of things to digest here and I think we could definitely improve our documentation in a few respects to help you here as well.

Your host-defined function, startTimer, is receiving an indirect function pointer from the wasm module. In WebAssembly C/C++ indirect function pointers are represented as 32-bit integers (you're seeing the value of 1). Unlike native platforms where the representation is the address of the native code in memory, the address of a function in WebAssembly is its index into the module's function table. The 1 that you're getting is not the export or function index, rather it's the index of the function within the module's function table.

What you'll need to do is to ensure that the module exports its function table (I'm not sure how to do this off-hand in C++). Once that's done though you'll need to acquire the function table, lookup slot 1, convert that to a Func of your expected signature, and call it.

Given the *.wat code you gisted I don't think the function table is exported so you may need to find the right argument to LLD to create an export for it.

Note that the examples in this repository work because the exports of the wasm module are known in advance. A more robust implementation would do string-based matching to find the right export. Again though that's just the index of exports, and that's different from the index space of the table itself.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 08 2021 at 21:00):

sergiizubchevskyy commented on Issue #2646:

Thank you for such a fast response!

Yes, here we had a similar idea BUT I forgot completely about the exports on the LLVM side. I was already using the --export-all option so I was convinced that everything was included. But I was wrong.

I adapted the compilation option and now I get the following exports:

![image](https://user-images.githubusercontent.com/44066210/107278767-1b1fe300-6a4e-11eb-93c0-5da23519bcf9.png)

The good news is that now I can in fact create a table, but the bad news was found here:

![image](https://user-images.githubusercontent.com/44066210/107279108-849ff180-6a4e-11eb-8d2b-4c9d4d4a0bd3.png)

Taken from here: https://github.com/bytecodealliance/wasmtime/blob/main/crates/c-api/include/doc-wasm.h

Or I'm missing something or there is no way, at least for now, to convert wasm_ref_t into wasm_func_t ?

view this post on Zulip Wasmtime GitHub notifications bot (Feb 08 2021 at 21:20):

sergiizubchevskyy commented on Issue #2646:

I tried reinterpreter_cast, it seems to work, but it is a bit strange, will test a bit more...

view this post on Zulip Wasmtime GitHub notifications bot (Feb 08 2021 at 21:59):

alexcrichton commented on Issue #2646:

Ah ok so with those exports you'll want to index into __indirect_function_table, and you should be able to use wasmtime_funcref_table_get thorugh the C API to load the function which is then callable.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 09 2021 at 10:05):

sergiizubchevskyy commented on Issue #2646:

Thank you for your help @alexcrichton! Will try this wasmtime_funcref_table_get.

Will close the issue :+1:

view this post on Zulip Wasmtime GitHub notifications bot (Feb 09 2021 at 10:05):

sergiizubchevskyy closed Issue #2646:

Hello!

I'm currently embedding the Wasmtime in the C/C++ and got an issue with the callbacks.

What I'm trying to achieve is to call a function, exported by the WASM script, from within the host system.

Here is the example:

![image](https://user-images.githubusercontent.com/44066210/107259486-f2d7ba80-6a34-11eb-8e60-207584a0009b.png)

From the host side, when conditions occur, I want to call the onTimer1 function.

This generates the following WASM code:

![image](https://user-images.githubusercontent.com/44066210/107259537-03883080-6a35-11eb-92df-8f1f5234b75a.png)

Now from the C/C++ host, I get the following exports:

![image](https://user-images.githubusercontent.com/44066210/107259689-36cabf80-6a35-11eb-9a3d-bec21ebf8153.png)

My issue is that when the script invokes the function "startTimer" in the callback parameter I get 1 (integer value of one). And if I try to get the callback with the 'wasm_extern_as_func' function it will misbehave because the index of the exported function in the exports is 2, not 1. If I hardcode the index of 2 it will work as expected.

I assumed that there is a need to create a table but I tried creating it using 'memory' (exports index 0) and '__table_base' (exports index 11), but the created table is always NULL (the module and exports are correct).

After I took a look at some examples I came to the conclusion that the only way to call a function is to know exactly the index of it in the exports, which can be found if I know the name of the function. For example (taken from https://github.com/WebAssembly/wasm-c-api/blob/master/example/table.c):
![image](https://user-images.githubusercontent.com/44066210/107260692-4a2a5a80-6a36-11eb-9e42-32ac440be6d7.png)

Am I missing something? Is the only way to get the function is to know the index of it in the exports? Is there a way to get a function via WASM table or something similar by using the value provided when the startTimer function is called?

Thank you in advance and sorry for the long post.


Last updated: Dec 23 2024 at 12:05 UTC