Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Capturing output from WASI binary (produced by TinyGo 0.26.0) #661

Open
thisisaaronland opened this issue Nov 24, 2022 · 3 comments
Open
Labels
❓ question Further information is requested

Comments

@thisisaaronland
Copy link

Summary

I want to use a WASI binary produced by TinyGo (0.26.0) in Python capturing the output from an exported function to a variable.

Specifically the parse method defined here:

https://github.com/sfomuseum/go-edtf/blob/wasi/cmd/parse-wasi/main.go

Which I can build and test like this:

$> tinygo build -o parse.wasm -target wasi ./cmd/parse-wasi/main.go

$> wasmer parse.wasm 2022-01-01
2022-01-01

If I run the following Python code (in a file called test.py):

#!/usr/local/bin/python3

from wasmer import engine, Store, Module, Instance, wasi
from wasmer_compiler_cranelift import Compiler

if __name__ == "__main__":

    r = open("parse.wasm", "rb")

    store = Store(engine.JIT(Compiler))
    module = Module(store, r.read())

    wasi_version = wasi.get_version(module, strict=True)

    wasi_env = wasi.StateBuilder('main').  \
        argument('2022-01-01'). \
        finalize()
    
    import_object = wasi_env.generate_import_object(store, wasi_version)

    instance = Instance(module, import_object)
    instance.exports._start()

I get this:

$> /usr/local/opt/python@3.10/bin/python3.10 ./test.py
2022-01-01

However, it's not clear how I can capture that output to a variable. Swapping out sys.stdout (or stderr) to a StringIO instance doesn't seem to work.

If I modify the code to pass an input pointer to instance.exports.parse like this:

#!/usr/local/bin/python3

from wasmer import engine, Store, Module, Instance, wasi
from wasmer_compiler_cranelift import Compiler

if __name__ == "__main__":

    r = open("parse.wasm", "rb")

    store = Store(engine.JIT(Compiler))
    module = Module(store, r.read())

    wasi_version = wasi.get_version(module, strict=True)

    wasi_env = wasi.StateBuilder('main').  \
        finalize()
    
    import_object = wasi_env.generate_import_object(store, wasi_version)
    instance = Instance(module, import_object)

    input = bytes('2022-01-01', 'utf-8')
    input_len = len(input)

    input_pointer = instance.exports.malloc(input_len)
    memory = instance.exports.memory.uint8_view(input_pointer)
    
    memory[0:input_len] = input
    memory[input_len] = 0

    instance.exports.parse(input_pointer)

I get the following error:

$> /usr/local/opt/python@3.10/bin/python3.10 ./test.py
Traceback (most recent call last):
  File "/usr/local/sfomuseum/go-edtf/./test.py", line 35, in <module>
    instance.exports.parse(input_pointer)
RuntimeError: RuntimeError: Parameters of type [I32] did not match signature [I32, I32, I32] -> []

Which I understand in principle but I am not sure I understand what is triggering it or why since it does not match the signature of the parse method in Go:

https://github.com/sfomuseum/go-edtf/blob/wasi/cmd/parse-wasi/main.go#L34

I feel like maybe I missing something obvious but I can't figure out what.

@thisisaaronland thisisaaronland added the ❓ question Further information is requested label Nov 24, 2022
@jaredweinfurtner
Copy link

I was able to capture the output via this solution: https://stackoverflow.com/a/29834357

out = OutputGrabber()
with out:
    instance.exports._start()
print(out.capturedtext)

@thisisaaronland
Copy link
Author

That's very interesting and I will investigate shortly. Thanks!

@thisisaaronland
Copy link
Author

It works! Thanks again.

https://github.com/sfomuseum/go-edtf-wasm/blob/wasi/python/test-wasmer.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
❓ question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants