1

我目前正在编写一个应用程序,该应用程序将为多个客户端提供类似的目的,但需要对其处理提供的数据的方式进行调整。从本质上讲,它将服务于相同的目的,但分发数据的方式完全不同。

所以我决定这样做: - 制作通用引擎库,它将包含所有方式的通用功能并提供默认界面,以确保不同的引擎将以相同的方式响应。- 为每一种运行方式编写一个特定的引擎……每一个都编译成它自己的.dll。

所以我的项目最终会得到一堆库,其中一些看起来像这样: project_engine_base.dll project_engine_way1.dll project_engine_way2.dll

现在在我们用于用户首选项的配置文件中会有一个引擎部分,以便我们可以决定使用哪个引擎:

[ENGINE]
Way1

所以在代码的某个地方我们想要做:

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

问题是......我将如何以这种方式导入我的 dll?甚至可能吗?如果没有,我能否就如何实现类似的运作方式获得一些建议?

我知道我可以一开始就导入所有的 dll,然后选择使用哪个引擎,但我的想法是我不想一劳永逸地导入太多引擎并浪费资源,我们也不想必须将所有这些 dll 发送给我们的客户。一位客户将使用一种引擎,另一位客户将使用不同的引擎。我们的一些客户可能会使用不止一个,因此我想将其外部化并允许我们的用户使用配置文件进行引擎切换。

有任何想法吗?

编辑:刚刚意识到,即使我的每个引擎在运行时动态加载并且不是全部在项目中引用时都会呈现相同的界面,我的项目也不会编译。所以我别无选择,只能将它们全部包含在我的项目中,不是吗?

这也意味着它们都必须运送给我的客户。配置中的设置仅使用我用来初始化我的引擎成员的类来决定。

或者

我可以将这些引擎中的每一个都编译为相同的名称。在我的主项目中只导入一个 dll,并且将一直使用该特定引擎。这将使我的客户无法将我们的应用程序用于他们自己的多个客户。除非他们愿意手动切换 dll。

有什么建议么?

编辑#2:此时看到我的选项,我还可以制作一个包含基本引擎以及所有子引擎和我的配置的大 dll,让用户选择。而不是引用多个 dll 并将它们全部发送。只需拥有一个巨大的并仅运送/参考那个。我也不太喜欢这个,因为这意味着将一个大 dll 发送给我所有的客户,而不仅仅是一两个满足客户需求的小 dll。不过,这仍然是我想出的最佳解决方案。

我仍在寻找更好的建议或答案来解决我原来的问题。谢谢。

4

2 回答 2

2

为每个引擎使用单独的 DLL,并在主项目中使用LoadLibrary根据配置加载特定引擎。

将您的引擎接口放在一些通用头文件中,所有引擎都将从该头文件中派生该接口,并且该接口也将在您的主项目中使用。

它可能看起来像这样:

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

在每个不同的引擎实现中,从 DLL 中导出一个函数,如下所示:

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

现在在您的主项目中只需使用 LoadLibrary 加载您感兴趣的 DLL,然后使用 getEngine 函数 GetProcAddress。

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();

导出函数的名称可能会被破坏,因此您可以在 DLL 中使用 DEF 文件或 extern "C",也不要忘记检查错误。

于 2009-05-14T19:10:05.187 回答
0

我得出的解决方案如下:

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));
}

我使用了丹尼尔的答案以及对他的答案的评论。经过一些额外的研究,我遇到了 LoadFrom 方法。

于 2009-05-22T19:59:10.043 回答