Stream: git-wasmtime

Topic: wasmtime / issue #9309 Help wanted: Accessing interfaces ...


view this post on Zulip Wasmtime GitHub notifications bot (Sep 25 2024 at 16:03):

LorDawid opened issue #9309:

Is there any way to access interfaces of other WASM components?

I've created a plugin1 with the following .wit representation:

package test:plugin1;

world plugin1 {
    import engine: interface {
        print: func(msg: string);
    }

    export plugin1i: interface {
        initialize-p1: func();
    }
}

And a plugin2 with the following .wit representation:

package test:plugin2;

world plugin2 {
    import engine: interface {
        print: func(msg: string);
    }

    import plugin1i: interface {
        initialize-p1: func();
    }

    export initialize-p2: func();
}

Which is supposed to use the plugin1's interface and call that method, but I haven't been able to find any documentation regarding this, so I'm wondering if it is even possible.

This does not work as the message component imports instance 'plugin1i', but a matching implementation was not found in the linker appears.

The only thing I seem to be able to do is:

    linker
        .instance("plugin1i")
        .unwrap()
        .func_wrap("initialize-p1", |_, (): ()| Ok(println!("Call")))
        .unwrap();

But the goal is not to define the functions myself, but rather to import them from other instances, and I'm also kinda curious about why this even works (are interfaces like instances under the hood? Why do I use .instance() to access a given interface?).

I could not find any documentation regarding this, so I hope that someone could help me here.

I'm trying to make a plugin system where dynamically loaded plugins can depend on each other (without having access to each other's source code), and I'm wondering if the component model is even the right thing to use here.

view this post on Zulip Wasmtime GitHub notifications bot (Sep 28 2024 at 16:33):

alexcrichton commented on issue #9309:

Thanks for the report! At this time linking like in the same manner as core wasm is not supported. That means that you can't take an export from one component and use it as the import of another component. To work around that you'll be required to use the host as you're doing here. Effectively you're on the right track and the goal is to fill out Ok(println!("Call")).

How exactly you fill that in depends on your use case. If you statically know the signatures, you can specialize to that. If you don't statically know the signatures (which I suspect is the case due to the plugin nature of this) you'll want to use func_new to define the function in LinkerInstance and Func::call. You'll need to do some "reflection" of sorts to iterate the exports of plugin component and to fill out the linker to instantiate the next component as well.

You're right this isn't well documented, and it's something we should improve! In the meantime though let me know if that doesn't work (or perhaps if it's so burdensome you change approaches altogether).

view this post on Zulip Wasmtime GitHub notifications bot (Nov 05 2024 at 12:39):

LorDawid closed issue #9309:

Is there any way to access interfaces of other WASM components?

I've created a plugin1 with the following .wit representation:

package test:plugin1;

world plugin1 {
    import engine: interface {
        print: func(msg: string);
    }

    export plugin1i: interface {
        initialize-p1: func();
    }
}

And a plugin2 with the following .wit representation:

package test:plugin2;

world plugin2 {
    import engine: interface {
        print: func(msg: string);
    }

    import plugin1i: interface {
        initialize-p1: func();
    }

    export initialize-p2: func();
}

Which is supposed to use the plugin1's interface and call that method, but I haven't been able to find any documentation regarding this, so I'm wondering if it is even possible.

This does not work as the message component imports instance 'plugin1i', but a matching implementation was not found in the linker appears.

The only thing I seem to be able to do is:

    linker
        .instance("plugin1i")
        .unwrap()
        .func_wrap("initialize-p1", |_, (): ()| Ok(println!("Call")))
        .unwrap();

But the goal is not to define the functions myself, but rather to import them from other instances, and I'm also kinda curious about why this even works (are interfaces like instances under the hood? Why do I use .instance() to access a given interface?).

I could not find any documentation regarding this, so I hope that someone could help me here.

I'm trying to make a plugin system where dynamically loaded plugins can depend on each other (without having access to each other's source code), and I'm wondering if the component model is even the right thing to use here.


Last updated: Dec 23 2024 at 12:05 UTC