Gå til indholdet

Arkitekturoversigt

Udvidelsesmodulsystemet er bygget af tre komponenter, alle under Components/:

Komponent Synlighed Ansvar
PluginApi Offentlig Rene abstrakte grænseflader og værdityper. Ingen Qt, ingen Scintilla, ingen MTE-interne headerfiler — kun standardbiblioteket.
PluginHost Intern Indlæser, ejer og fordeler til udvidelsesmodulerne. Qt er en implementeringsdetalje her (den bruger QPluginLoader under motorhjelmen).
Plugins Egetudviklede Eksempler og indbyggede udvidelsesmoduler; hvert sit CMake-mål, der kun afhænger af PluginApi (og af Qt, når den indbyggede backend bruges).

Designprincipper

  • Backend-uafhængig kontrakt. Alle PluginApi-typer ligger i namespace MTE::plugin og må ikke inkludere nogen Qt-, Scintilla- eller MTE-intern headerfil. Det er dét, der lader en fremtidig Python-backend opfylde den samme kontrakt uden modstand fra Qt.
  • Ingen tredjepartstyper på tværs af den offentlige API. Udvidelsesmoduler ser aldrig Scintilla- eller Qt-typer; værten oversætter mellem den interne IEditorView og den offentlige IEditorService.
  • RAII overalt. At registrere en kommando, et menupunkt, et dokpanel eller et hændelsesabonnement giver et symbol eller et abonnementshåndtag tilbage. Ødelægger man det, afmeldes bidraget. Udvidelsesmoduler holder deres symboler som medlemmer, så alting rives ned af sig selv i shutdown().

Livscyklus

Hvert udvidelsesmodul implementerer én enkelt grænseflade, IPlugin:

class IPlugin {
public:
    virtual ~IPlugin() = default;
    virtual PluginInfo info() const = 0;
    virtual bool       initialize(IPluginContext& ctx) = 0;
    virtual void       shutdown() noexcept = 0;
};
  • info() giver POD-metadata tilbage (id, name, version, vendor, description, apiVersion).
  • initialize(ctx) modtager en IPluginContext, der virker som tjenestekatalog. Udvidelsesmodulet henter de tjenester, det skal bruge, og registrerer sine kommandoer, menuer, paneler og hændelsesabonnementer.
  • shutdown() kører på vej ud; fordi bidragene er RAII-symboler, er den almindelige nedrivning som regel blot at lade medlemmerne blive ødelagt.

Ingen genindlæsning under kørsel

At slå et udvidelsesmodul til eller fra, at installere det og at afinstallere det får alt sammen først virkning ved næste start. Værten indlæser eller udlæser aldrig modulkode under kørsel — det holder modellen enkel og går uden om Windows' problem med, at man »ikke kan slette en indlæst DLL«.

Opdagelse

Værten gennemsøger i denne rækkefølge:

  1. <exe-dir>/Plugins/ — de medleverede egetudviklede udvidelsesmoduler.
  2. <AppLocalData>/Plugins/ — installationsmappen pr. bruger.
  3. Stier fra miljøvariablen MTE_PLUGIN_PATH.

Hver mappe gennemsøges for løse biblioteker og for ét niveau af umiddelbare undermapper (det <id>/-layout pr. udvidelsesmodul, som et installationsprogram frembringer). Opdagelsen går ikke dybere ned.