Skip to main content

Plugin/Extension System Design

VSCode and Chrome has a great extension ecosystem, allowing developers to enhance the functionality of them. How can we design such a system?

Architecture Overview

For interpreted languages like Python and JavaScript, the main program can simply read the plugins' scripts. e.g. JavaScript library can be import/require. Python has importlib. The plugins can be run within the main programs process and thread.

For other compiled languages like Rust, it's more complicated. There are many options.

Dynamic Library

Shared Object and DLL

Dynamic-link library (.ddl) is the shared library on Windows.

Shared Object (.so) is the shared library for Linux.

A library/plugin can be compiled into a shared library where an app can import dynamically. User just need to provide the library file. These libraries have to expose its functions in some specific standard, such as C API.

WebAssembly

Another similar (but different) concept is WebAssembly. WebAssembly runs in many languages. A program can import a WebAssembly module and import functions defined in it. This works similarly to shared libraries.

Binary Sidecar

Compiling plugins into binaries as sidecars is another choice. The main difference is, the main program will have to run this as a separate process instead of importing as a library.

Pros: more flexible, don't have to deal with the interface between languages.

The problem with this is that the main program and plugins run in different processes and have to communicate. This is called IPC (Inter-Process Communication). Here are some options.

Pipe

Pipe can be used to communicate between the main and child process. More specifically stdin, stdout, stderr. Usually for parent-child process communication.

Named Pipe

Named pipes, also known as FIFOs (First-In-First-Out), are similar to pipes but can be used for communication between unrelated processes. They are created as special files in the file system, and processes can read from and write to them.

Message Queue

MQTT is an example, this requires a separate message queue server.

Shared Memory

Multiple processes can access a common region of memory. This allows processes to share data directly, without the need for copying data between them. However, careful synchronization is required to avoid data corruption.

Sockets

Based on network. e.g. TCP connection between a client and server, sending raw bytes to each other.

HTTP Server

Similar to sockets, but a fully featured HTTP server with more functionalities, such as Web Soceket, GET/POST request.