extism / java-sdk

Extism Java Host SDK enables Java programs to embed and run WebAssembly plugins.
BSD 3-Clause "New" or "Revised" License
27 stars 7 forks source link

Loading multiple wasm modules does not work #25

Closed amysyk-viax-io closed 5 months ago

amysyk-viax-io commented 7 months ago

I have two simple wasm modules. One of them exports function greetA and the second one function greetB.

As result of calling greetA I get the following exception org.extism.sdk.ExtismException: Function not found: greetA. Here is an example

final var sourceResolver = new WasmSourceResolver();
final var a = sourceResolver.resolve("a", Files.readAllBytes(Path.of("moduleA.wasm")));
final var b = sourceResolver.resolve("b", Files.readAllBytes(Path.of("moduleB.wasm")));
final var manifest = new Manifest(List.of(a, b));

try (var plugin = new Plugin(manifest, true, null)) {
    plugin.call("greetA", "java");
}

At the same time, the function greetB is available and returns result as expected.

kevinduffey commented 7 months ago

I am adding a "thought" here mostly because I was just made aware of this neat feature calling "linking" between WASM modules. It appears that you are exporting functions from each, but when using 2 (or more) wasm modules in a single manifest, I would assume one would be importing something from the other (in your example).

I would say download the free modsurfer and load up both WASM modules, see what are importing/exporting (https://dylibso.com/products/modsurfer/) to get a glimpse of each. However, I am following this because I am now curious what is going on here. It's as if the B wasm module is overriding the A wasm module, but not sure why that would be because they export different function names. Unless you have a mistake in one of your exports? But it does seem as if you should be able to call either so I am curious what is going on internally.

zshipko commented 7 months ago

At the same time, the function greetB is available and returns result as expected.

This is the expected behavior - Extism expects one "main" module and the other modules are exposed to that main module but aren't callable themselves. In this case b is being interpreted as the main module because it's listed last and there is no main module specified - that's why greetB is callable, however greetA is only exposed to the other module as a::greetA (where a is the wasm namespace)

So, if you need to call greetA and greetB they should both be part of the same module but if you would like to call a::greetA from inside greetB your current setup should work.

bhelx commented 7 months ago

Note there is a tool called "wasm-merge" that comes with binaryen that accomplishes what I think you are trying to do statically https://github.com/WebAssembly/binaryen

kevinduffey commented 7 months ago

Ah yes! That makes sense! Interesting that it chooses the last in the list and doesnt throw an error. I wonder if maybe it should throw an error indicating two (or more) modules having main() in it?

zshipko commented 7 months ago

Yeah it does seem like if all modules in a manifest are named and none are named main we could raise an error.

amysyk-viax-io commented 7 months ago

Thank you for quick response here. Everything is clear now.

bhelx commented 5 months ago

Thanks again for filing! feel free to re-open if you still feel blocked.