c ++ - Modul og klasserhåndtering (dynamisk linking)

Indlæg af Hanne Mølgaard Plasc

Problem



Kom ind i et problem, og jeg søger det bedste løsningskoncept/teori.


Jeg har et system, der skal bruge objekter. Hver objekt, som systemet bruger, har et kendt interface, der sandsynligvis er implementeret som en abstrakt klasse. Grænsefladerne er kendt på byggetiden og vil ikke ændre sig. Den nøjagtige implementering, der skal bruges, varierer, og jeg har ingen anelse om tid, hvilket modul vil give det. Den eneste garanti er, at de vil give grænsefladen. Klassenavnet og modulet (DLL) kommer fra en config-fil eller kan ændres programmatisk.


Nu har jeg alt, hvad der er oprettet i øjeblikket ved at bruge et relativt simpelt system, oprette noget som sådan (omskrevet pseudokode, bare for at vise det grundlæggende):


struct ClassID
{
    Module * module;
    int number;
};

class Module
{
    HMODULE module;
    function<void * (int)> * createfunc;

    static Module * Load(String filename);

    IObject * CreateClass(int number)
    {
        return createfunc(number);
    }
};

class ModuleManager
{
    bool LoadModule(String filename);

    IObject * CreateClass(String classname)
    {
        ClassID class = AvailableClasses.find(classname);
        return class.module->CreateObject(class.number);
    }

    vector<Module*> LoadedModules;
    map<String, ClassID> AvailableClasses;
};


Moduler har et par eksporterede funktioner for at give antallet af klasser, de giver, og navnene/id'erne af dem, der derefter gemmes. Alle klasser stammer fra IObject, som har en virtuel destructor, gemmer kildemodulet og har nogle metoder til at få klassen 'ID, hvilken grænseflade den implementerer og sådan.


Det eneste problem med dette er, at hvert modul skal indlæses manuelt et sted (angivet i config-filen, i øjeblikket). Jeg vil gerne undgå at gøre dette eksplicit (uden for ModuleManager, inden jeg ikke er virkelig bekymret for, hvordan den er implementeret.


Jeg vil gerne have et lignende system uden at skulle klare indlæsning af modulerne, bare oprette et objekt og (når det hele er oprettet) vises det magisk.


Jeg mener, at det ligner det, som COM skal have på nogle måder. Jeg kiggede kort på COM-systemet, men det synes at være overkill uden tro. Jeg har kun brug for de klasser, der er kendt inden for mit system, og behøver ikke alle de andre funktioner, den håndterer, bare implementeringer af grænseflader, der kommer fra et eller andet sted.


Min anden ide er at bruge registreringsdatabasen og holde nøglen med alle de kendte/registrerede klasser og deres kildemoduler og tal, så jeg kan bare se dem op og det ser ud til at Manager::CreateClass finder og gør objektet magisk. Dette virker som en levedygtig løsning, men jeg er ikke sikker på om den er optimal, eller hvis jeg genopfinder mig noget.


Så efter alt det er mit spørgsmål, hvordan man håndterer dette? Er der en eksisterende teknologi, hvis ikke, hvordan bedst kan jeg oprette mig selv? Er der nogen gotchas at jeg skal kigge efter?

Bedste reference


COM er meget sandsynligt, hvad du vil have. Det er meget bredt, men du behøver ikke at bruge alle funktionerne. Du behøver f.eks. Ikke kræve, at deltagerne registrerer GUID'er, du kan definere din egen mekanisme til oprettelse af forekomster af grænseflader. Der er en række skabeloner og andre mekanismer, der gør det nemt at oprette COM-grænseflader. Hvad mere er, da det er en standard, er det nemt at dokumentere kravene.


En meget vigtig ting at huske på er at importere/eksportere C ++-objekter kræver, at alle deltagere bruger samme compiler. Hvis du tror, ​​at det nogensinde kunne være et problem for dig, så skal du bruge COM. Hvis du er glad for at acceptere denne begrænsning, så kan du fortsætte som du er.

Andre referencer 1


Jeg ved ikke, om der findes nogen teknologi til at gøre dette.


Jeg ved, at jeg arbejdede med et system, der lignede meget herpå. Vi brugte XML-filer til at beskrive de forskellige klasser, som forskellige moduler stilles til rådighed. Vores tilsvarende af ModuleManager ville parse xml-filerne for at bestemme, hvad der skal oprettes for brugeren i løbetid baseret på det klassenavn, de leverede og systemets konfiguration. (Anmodning om et objekt, der implementeret grænseflade 'I', kunne give noget af genstande 'A', 'B' eller 'C' tilbage afhængigt af, hvordan systemet blev konfigureret.)


Den store gotcha vi fandt var, at systemet var meget skørt og til tider svært at debug/forstå. Bare at læse gennem koden var det ofte næsten umuligt at se, hvilken konkret klasse der blev etableret. Vi fandt også, at vedligeholdelse af XML skabte flere fejl og overhead end forventet.


Hvis jeg skulle gøre det igen, ville jeg beholde designmønsteret for at eksponere klasser fra DLL'er gennem grænseflader, men jeg ville ikke forsøge at opbygge et centralt register over klasser, og heller ikke ville jeg udlede alt fra en base klasse som IObject.


Jeg vil i stedet gøre hvert modul ansvarligt for at udsætte sine egne fabriksfunktioner for at instantiere objekter.