2009-05-14 5 views
1

Je suis en train d'écrire une application qui servira un but similaire pour plusieurs clients, mais qui nécessite des adaptations pour gérer les données qu'elle contient. Essentiellement, cela servira le même but, mais distribuera des données totalement différentes. - J'ai créé une bibliothèque de moteurs commune qui contiendra les fonctionnalités communes de toutes les manières et présentera l'interface par défaut pour que les différents moteurs répondent de la même manière. -Ecrit un moteur spécifique pour chaque façon de fonctionner .... chacun compile dans son propre .dll.Managed C++ - Importation de différentes DLL basées sur le fichier de configuration

donc mon projet va se retrouver avec un tas de bibliothèques avec un peu ressembler à ceci: project_engine_base.dll project_engine_way1.dll project_engine_way2.dll

maintenant dans le fichier de configuration que nous utilisons pour les préférences de l'utilisateur là-bas sera une partie du moteur afin que nous puissions décider de quel moteur utiliser:

[ENGINE] 
Way1 

donc, quelque part dans le code que nous voulons faire:

If (this->M_ENGINE == "Way1") 
    //load dll for way1 
Else If (this->M_ENGINE == "Way2") 
    //load dll for way2 
Else 
    //no engines selected...tell user to modify settings and restart application 

La question est ... Comment vais-je importer mes DLLs de cette façon? Est-ce même possible? Si non, puis-je obtenir des suggestions sur la façon de parvenir à un fonctionnement similaire? Je savais que je pouvais simplement importer toutes les DLL dès le départ et choisir le moteur à utiliser, mais l'idée était que je ne voulais pas importer trop de moteurs pour rien et gaspiller des ressources et nous didn didn Je ne veux pas avoir à expédier tous ces DLL à nos clients. Un client utilisera un moteur et un autre en utilisera un autre. Certains de nos clients en utiliseront plus d'un, d'où la raison pour laquelle je voulais externaliser cela et permettre à nos utilisateurs d'utiliser un fichier de configuration pour la commutation du moteur.

Des idées? Je viens de réaliser que même si chacun de mes moteurs présentait la même interface s'ils étaient chargés dynamiquement à l'exécution et n'étaient pas tous référencés dans le projet, mon projet ne compilerait pas. Donc je n'ai pas le choix de les inclure tous dans mon projet, n'est-ce pas?

Cela signifie également qu'ils doivent tous être expédiés à mes clients. Les paramètres de la configuration ne dictent qu'avec la classe que j'utiliserais pour initialiser mon membre de moteur.

OU

je pouvais avoir chacun de ces moteurs est établi pour le même nom. Importer seulement une DLL dans mon projet principal et ce moteur particulier serait utilisé tout le temps. Cela rendrait mes clients incapables d'utiliser notre application pour plusieurs clients de leur choix. Sauf s'ils étaient prêts à changer manuellement de DLL. Yuck

Une suggestion? A ce stade, voyant mes options, je pourrais aussi faire une grosse DLL contenant le moteur de base ainsi que tous les enfants et ma configuration pour laisser l'utilisateur choisir. Au lieu de référencer plusieurs DLL et de les expédier tous. Juste en avoir un énorme et expédier/référence celui-là seulement. Je ne suis pas trop friand de cela, car cela signifie envoyer une grosse DLL à tous mes clients au lieu d'un ou deux petits qui répondent à leurs besoins.C'est toujours la meilleure solution que j'ai trouvée.

Je suis toujours à la recherche de meilleures suggestions ou réponses à ma question initiale. Merci.

Répondre

0

La solution que je suis venu est le suivant:

Engine_Base^ engine_for_app; 
Assembly^ SampleAssembly; 
Type^ engineType; 

if (this->M_ENGINE == "A") 
{ 
    SampleAssembly = Assembly::LoadFrom("path\\Engine_A.dll"); 

    engineType = SampleAssembly->GetType("Engine_A"); 
    engine_for_app = static_cast<Engine_Base^>(Activator::CreateInstance(engineType, param1, param2)); 
} 
else 
{ 
    SampleAssembly = Assembly::LoadFrom("path\\Engine_B.dll"); 

    engineType = SampleAssembly->GetType("Engine_B"); 
    engine_for_app = static_cast<Engine_Base^>(Activator::CreateInstance(engineType, param1, param2, param3, param4)); 
} 

J'ai utilisé la réponse de Daniel et les commentaires qui ont été faites sur sa réponse. Après quelques recherches supplémentaires, je suis tombé sur la méthode LoadFrom.

2

Utilisez des DLL distinctes pour chaque moteur et utilisez LoadLibrary dans votre projet principal pour charger le moteur spécifique en fonction de la configuration. Avoir l'interface de votre moteur dans un fichier d'en-tête commun dont tous les moteurs dériveront et cette interface sera également utilisée dans votre projet principal.

Il pourrait ressembler à ceci: Dans chaque autre exportation de mise en œuvre du moteur

// this should be an abstract class 
class engine { 
public: 
    virtual void func1() = 0; 
    virtual void func2() = 0; 
... 
}; 

fonction de la DLL, quelque chose comme ceci:

// might aswell use auto_ptr here 
engine* getEngine() { return new EngineImplementationNumberOne(); } 

Maintenant, dans votre projet principal simplement charger la DLL que vous Vous êtes intéressé à utiliser LoadLibrary, puis GetProcAddress la fonction getEngine.

string dllname; 

if (this->M_ENGINE == "Way1") 
    dllname = "dllname1.dll";   
else if (this->M_ENGINE == "Way2") 
    dllname = "dllname2.dll"; 
else 
    throw configuration_error(); 

HMODULE h = LoadLibraryA(dllname.c_str()); 
typedef engine* (*TCreateEngine)(); 

TCreateEngine func = (TCreateEngine)GetProcAddress(h, "getEngine"); 
engine* e = func(); 

Le nom de la fonction exportée sera probablement obtenir mutilée, de sorte que vous pouvez soit utiliser des fichiers DEF ou extern « C » dans vos DLL, aussi ne pas oublier de vérifier les erreurs.

+0

Je crois que la définition de type TCreateEngine est fausse (pourrait-elle être: typedef engine * (* TCreateEngine)(); ??), mais l'anwer est bonne. +1 –

+0

Oh, et n'oubliez pas d'utiliser extern "C" lors de la déclaration et la définition de la fonction, sinon le compilateur déformera les noms. –

+0

oui le typedef était faux, je l'ai corrigé, merci. à propos de l'extern "C", je l'ai mentionné dans un commentaire dans le code, mais je vais le déplacer à la réponse réelle afin que ce soit plus clair. –

Questions connexes