Comments (9)
As @MarkMcCaskey said, I'm not sure it is expected to call an exported function with WASI. WASI expects one entry point, which is a _start
function.
I tried the following:
#include <stdio.h>
extern "C" {
int hello() __attribute__((used));
int hello() {
printf("Hello from an exported function!");
return 42;
}
}
int main(int argc, char **argv)
{
if (argc < 2) {
printf("Hello, WASI!\n");
} else {
printf("Hello, %s!\n", argv[1]);
}
}
Calling _start
(i.e. main
) works well, but calling hello
correctly returns 42
(exactly wasm.I32(42)
) but Hello from an exported function!
isn't printed on stdout.
@MarkMcCaskey Any idea why?
from wasmer-go.
It seems I was searching in the wrong direction: the panic did not result from any C or C++ code related issues. It was our Go code all along. Specifically, some leftover code from extending the import object in an earlier version of our module:
importObject := wasm.NewDefaultWasiImportObject()
imports, _ := importObject.Imports()
importObject.Extend(*imports)
instance, _ := module.InstantiateWithImportObject(importObject)
That messed up the import object, even though the exported functions still seemed to exist. Changing the code above into:
importObject := wasm.NewDefaultWasiImportObject()
instance, _ := module.InstantiateWithImportObject(importObject)
... solved the issue. As always, thanks for your support and feedback!
from wasmer-go.
Closing the issue since the initial problem is solved :-). We are looking at the other issue.
from wasmer-go.
It seems this problem is more generic then just calling main() - the same panic error message is returned when calling any exported C++ function.
To run our C++ based framework, we need to invoke an exported function pred()
in a WASI standalone Webassembly binary compiled using Emscripten. The main() and pred() functions are defined as follows in the cpp file:
extern "C" {
int pred() __attribute__((used));
int pred() {
printf("Running pred()\n");
double *prediction = cpwbart();
double result = prediction[0] + mu;
return (0);
}
}
int main() {
printf("Running main()\n");
double *prediction = cpwbart();
double result = prediction[0] + mu;
return (0);
}
We call pred()
as follows:
importObject := wasm.NewDefaultWasiImportObject()
imports, err := importObject.Imports()
if err != nil { panic(err) }
err = importObject.Extend(*imports)
if err != nil { panic(err) }
bytes, err := wasm.ReadBytes("bart_snapshot1.wasm")
if err != nil { panic(err) }
module, err := wasm.Compile(bytes)
if err != nil { panic(err) }
instance, err := module.InstantiateWithImportObject(importObject)
if err != nil { panic(err) }
defer instance.Close()
fmt.Println(instance.Exports); // pred is available in the exports
message, err := instance.Exports["pred"]()
if err != nil { panic(err) }
// result: panic: Failed to call the `pred` exported function.
WAVM is able to invoke this function without any problem, however.
Maybe related to the Wasmer issue here: wasmerio/wasmer#1024 ?
from wasmer-go.
As WASI ABI functions can now be invoked using wasmerio/wasmer#1036, I also tried to call a WASI function from go-ext-wasm with a build based on that PR:
[dependencies]
wasmer-runtime-c-api = { git = "https://github.com/wasmerio/wasmer", branch = "feature/experimental-wasi-invoke" }
Yet the resulting go-ext-wasm lib with its new libwasmer_runtime_c_api.so still results in:
result: panic: Failed to call the `pred` exported function.
So there could be some go-ext-wasm specific issue at play? On the other hand, the PR clearly states "...in wasmer cli", so probably the c-api code just needs some similar modifications. It is also possible I should go about incorporating the PR differently, of course!
from wasmer-go.
As @MarkMcCaskey said, I'm not sure it is expected to call an exported function with WASI. WASI expects one entry point, which is a
_start
function.
I do understand. Yet seeing that the WebAssembly ecosystem moves towards general use of the WASI ABI, it often does help to be able to invoke other functions outside of main()
or, more to the point, _start()
.
Hello from an exported function! isn't printed on stdout.
Probably that's the result of the string not ending in "\n", based upon experience I expect the following will print to stdout:
printf("Hello from an exported function!\n");
I sought to replicate our issue with a minimal example was well. Do let me know if you'd prefer it if I open a new issue for the following.
Some C++ code that seems to replicate the issue:
#include <stdio.h>
#include <string>
extern "C" {
int big_data_function() __attribute__((used));
int big_data_function() {
std::string itv = R"~~~~(
200 200 23
3
1 13 0 0
2 0 0 15794.29427
)~~~~";
std::fwrite(itv.c_str(), 1, 20, stdout); // print first 20 bytes
return (0);
}
}
int main(int argc, char **argv)
{
printf("Hello, WASI!\n");
}
Compile with:
wasic++ -O3 test1.cpp -o test1.wasm
Then successfully run test1.wasm
with the latest Wasmer CLI:
> wasmer run test1.wasm -i big_data_function
WARNING: Invoking a function with WASI is not officially supported in the WASI standard yet. Use this feature at your own risk, things may not work!
200 200 23
big_data_function returned [I32(0)]
But when running the same function from go-ext-wasm
using the following code:
package main
import (
"fmt"
wasm "github.com/wasmerio/go-ext-wasm/wasmer"
)
func main() {
importObject := wasm.NewDefaultWasiImportObject()
imports, err := importObject.Imports()
if err != nil { panic(err) }
err = importObject.Extend(*imports)
if err != nil { panic(err) }
bytes, err := wasm.ReadBytes("test1.wasm")
if err != nil { panic(err) }
module, err := wasm.Compile(bytes)
if err != nil { panic(err) }
instance, err := module.InstantiateWithImportObject(importObject)
if err != nil { panic(err) }
defer instance.Close()
fmt.Println(instance.Exports);
message, err := instance.Exports["big_data_function"]()
if err != nil { panic(err) }
fmt.Println(message)
}
... for now still using our wasi_snapshot_preview1 workaround ...
> wasm2wat test1.wasm > test1.wat && sed -i 's/wasi_unstable/wasi_snapshot_preview1/g' test1.wat && wat2wasm test1.wat > test1.wasm
> go run test1.go
... Go panics with Failed to call the
big_data_function exported function
:
map[_start:0x49cc80 big_data_function:0x49cc80]
panic: Failed to call the `big_data_function` exported function.
goroutine 1 [running]:
main.main()
/mnt/c/Users/robin/CPPtest/test1.go:30 +0x3ab
exit status 2
I find it difficult to pinpoint the problem. It seems I am close, but not quite there yet. The issue does seem to have to do with invoking C++ functions and/or C/C++ libs from go-ext-wasm.
from wasmer-go.
Can you check the exported function exists:
big_data_function, exists := instance.Exports["big_data_function"]
if false == exists {
panic("The exported function doesn't exist")
}
message, err := big_data_function()
// …
from wasmer-go.
Sure! When I do the following:
...
fmt.Println(instance.Exports);
big_data_function, exists := instance.Exports["big_data_function"]
if false == exists {
panic("The exported function doesn't exist")
} else {
fmt.Println("Exported function *exists*")
}
fmt.Println(big_data_function)
...
I get:
map[_start:0x49cc80 big_data_function:0x49cc80]
Exported function *exists*
0x49cc80
Followed, of course, by, the panic: Failed to call the 'big_data_function' exported function.
later on in the code.
If I can help out in any other way, just let me know!
from wasmer-go.
Also, exported functions do indeed not seem to print to stdout, either with or without trailing '\n' - don't know what is happening there.
from wasmer-go.
Related Issues (20)
- Why does converting to I32 with a uint32 value panic if the I32 type is sign agnostic?
- How to support simd instructions in wasmer-go?
- Error print?
- Error executing?
- No error print?
- Allocate memory fail?
- mv dir/foo dir/bar: applet not found
- Rename error message error?
- How can i edit a program with golang and build it with tiny-go, then i can get wasm file?
- loop call wasmer instance export func will occur panic
- Multi-value return support
- Memory leaks after upgrading bindings to 3.3.0
- Issue compiling, parses `-lwasmer` flag as directory? HOT 1
- Is this project still maintained? HOT 1
- Can we run Javy compiled JS program with wasmer-go?
- Is it possible to access un-exported data
- WebAssembly translation error: Unsupported feature: proposed simd operator F64x2PromoteLowF32x4
- Executing HTTP Requests from within WASM functions ?
- support setting bytes for stdin HOT 4
- panic: runtime error: invalid memory address or nil pointer dereference HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from wasmer-go.