WebAssembly / component-model

Repository for design and specification of the Component Model
Other
977 stars 82 forks source link

Are (more complex) event-based plugin mechanisms possible/a target? #195

Open meastp opened 1 year ago

meastp commented 1 year ago

Hi,

I read the meeting notes and follow your progress and am really enthusiastic about the component model and what it will enable for wasm usage. Thanks for your work! :)

I'm sorry, I'm not able to compress this into a short question, bear with me :)

Although my example is specific, the questions are general.

Anyway, I've been thinking the past days about more complex plugin architectures/systems in use today.

One example that I'm just a bit familiar with, is Qt's plugin system. It uses events (signals/slots are the Qt terms) and enables writing plugins in C++. There is also pyQt - a third party project for writing Qt applications in Python. Since this uses Qt's events-system (signals/slots) one is able to choose what parts of the application is written in C++ and Python, which is really nice.

An example of an application that use this is QGIS, which is an open source desktop GIS. The core is written in C++/Qt and the recommended way to write plugins is in Python. Which is mostly okay for tasks that aren't performance sensitive.

C++ plugins aren't recommended simply because they have to be ABI-compatible with every distribution of QGIS (as there is no stability-guarantees, this means one has to build the plugin for every version, on every architecture). So making a plugin outside the official repo is a nightmare.

So, one has to choose between performance (C++/Qt) or ease of distribution and use (Python/pyQT). Not ideal.

This is where wasm and the component model might make a huge difference, but I don't know how toolable and complex this task might be, or if it's even possible or a goal?

(Another example or this type of plugin model is Jenkins, a Java CI project which is very extensible (I think plugins need to be written in Java or JVM, not sure about this)).

--

  1. Could the wasm runtime hook into the event system of an application and expose (component model) functions to be able to write plugins in wasm (and therefore almost any language!)?
  2. Most plugin arhitectures today use classes/objects and inheritance even though the actual communication is event-based (at least I think so). The component model doesn't have objects, but I guess opaque references/pointers functions could be used for this in the component model if neccessary?

example:

struct myobj;

myobj* create_myobj(param1, param2)

void manipulate_myobj(myobj*, param1, param2, param3)

void destroy_myobj(myobj*) 
  1. If this is possible, the interface from the component model directly is a bit cumbersome, so perhaps some tooling would be able to transform this interface into classes/objects in a particular language (example could be java or python or ..., I happen to be a C++ dev, so thats why my example is C++ :) )?

class cpp_myobj
{
   myobj* _obj;
   public:
   cpp_myobj(param1, param2); // constructor
   void manipulate_myobj(param1, param2, param3);
   ~cpp_myobj(); //destructor
}

or something similar for java or Python...?

  1. The performance wouldn't be as good as a direct plugin to the host application (my example: Qt/C++ plugin), but for most plugins that's not neccessary. For those that need more performance, that's a use case for some of the future features - being able to share (some) memory with the host.

I would love to hear your thoughts about this? :)

lukewagner commented 1 year ago

Hi @meastp and thanks for your interest and good questions. First, at a high-level, what you're describing is definitely a pattern we've seen across different language runtimes (incl JS and Python) and definitely something we want components to be well-suited to address via embedding into those language runtimes.

Going through your questions:

  1. Yes, there is a goal of making components embeddable into systems that execute component code in response to events. Systems have two options: call component exports in response to events (as you can see in the wasi-http's proxy world or, once streams are added (TODO), have the component imports a function returning a stream of events.
  2. Resource types roughly fill the role traditionally served by classes and could be mapped to classes in OOP languages. See the JS embedding for a sketch of resources and functions could be bound to classes/methods.
  3. Similarly, resource types and bindings generation is aimed at this.
  4. Yep!