C++ 托管C++;-根据配置文件导入不同的DLL

C++ 托管C++;-根据配置文件导入不同的DLL,c++,visual-c++,dll,dllimport,C++,Visual C++,Dll,Dllimport,我目前正在编写一个应用程序,该应用程序将为多个客户机提供类似的用途,但需要对其如何处理提供的数据进行调整。从本质上讲,它将服务于相同的目的,但发布数据的方式完全不同 所以我决定这样做: -创建通用引擎库,该库将保存所有方式的通用功能,并提供默认界面,确保不同引擎以相同的方式响应。 -为每种运行方式编写一个特定的引擎…每种引擎都编译成自己的.dll 因此,我的项目将以一组库结束,其中一些库如下所示: project_engine_base.dll project_engine_way1.dll p

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

所以我决定这样做: -创建通用引擎库,该库将保存所有方式的通用功能,并提供默认界面,确保不同引擎以相同的方式响应。 -为每种运行方式编写一个特定的引擎…每种引擎都编译成自己的.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。这仍然是我想出的最好的解决方案

我仍然在寻找更好的建议或回答我原来的问题。
谢谢。

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

将引擎接口放在所有引擎都将从中派生的公共头文件中,该接口也将用于主项目中

可能是这样的:

// this should be an abstract class
class engine {
public:
     virtual void func1() = 0;
     virtual void func2() = 0;
...
};
// might aswell use auto_ptr here
engine* getEngine() { return new EngineImplementationNumberOne(); }
在每个不同的引擎实现中,从DLL导出一个函数,如下所示:

// this should be an abstract class
class engine {
public:
     virtual void func1() = 0;
     virtual void func2() = 0;
...
};
// might aswell use auto_ptr here
engine* getEngine() { return new EngineImplementationNumberOne(); }
现在在您的主项目中,只需加载您感兴趣的DLL,然后使用LoadLibrary和GetProcAddress调用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();

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

我找到的解决方案如下:

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));
}
Engine\u Base^Engine\u用于应用程序;
组件^相同组件;
类型^engineType;
如果(此->M_引擎==“A”)
{
samplessembly=Assembly::LoadFrom(“path\\Engine_A.dll”);
engineType=samplessembly->GetType(“引擎A”);
_app的引擎_=static_cast(Activator::CreateInstance(engineType,param1,param2));
}
其他的
{
samplessembly=Assembly::LoadFrom(“path\\Engine_B.dll”);
engineType=samplessembly->GetType(“引擎B”);
_app的引擎_=static_cast(Activator::CreateInstance(engineType,param1,param2,param3,param4));
}

我使用了丹尼尔的答案和对他的答案的评论。经过一些额外的研究后,我发现了LoadFrom方法。

我认为TCreateEngine类型定义是错误的(可能是:typedef engine*(*TCreateEngine)(;?),但答案是好的+1Oh,在声明和定义函数时不要忘记使用extern“C”,否则编译器将损坏名称。是的,typedef是错误的,我更正了它,谢谢。关于外部“C”,我在代码中提到了它,但是我将把它移到实际答案,所以它会更清楚。我在管理C++中做这一切不是本地的。是否同样工作?如果你的类不是管理C++的,没有理由不起作用。如果它们是托管类(用“ref”关键字声明),则可以使用Assembly类而不是LoadLibrary和GetProcAddress。