Управляемый C ++ - импорт различных библиотек DLL на основе файла конфигурации - PullRequest
1 голос
/ 14 мая 2009

В настоящее время я пишу приложение, которое будет служить аналогичной цели для нескольких клиентов, но требует адаптации к тому, как оно будет обрабатывать поступающие данные. По сути, он будет служить той же цели, но раздает данные совершенно по-разному.

Итак, я решил продвинуться так: -Создание общей библиотеки движков, которая будет содержать общие функциональные возможности всех способов и представлять интерфейс по умолчанию, гарантирующий, что разные движки будут реагировать одинаково. -Пишите конкретный движок для каждого способа функционирования .... каждый компилируется в свой собственный .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 (s) таким образом? Это вообще возможно? Если нет, могу ли я получить некоторые предложения о том, как добиться аналогичного способа функционирования?

Я знаю, что я мог бы просто импортировать все dll в самом начале и просто выбрать, какой движок использовать, но идея заключалась в том, что я не хотел импортировать слишком много движков для ничего и тратить ресурсы, и мы не сделали ' Я не хочу отправлять все эти библиотеки нашим клиентам. Один клиент будет использовать один двигатель, другой - другой. Некоторые из наших клиентов будут использовать более одного, возможно, поэтому, я решил использовать это для внешних целей и позволить нашим пользователям использовать файл конфигурации для переключения двигателя.

Есть идеи?

EDIT: Просто понял, что, хотя каждый мой движок будет представлять один и тот же интерфейс, если они загружаются динамически во время выполнения и не все ссылки в проекте, мой проект не будет компилироваться. Так что у меня нет выбора, но включить их всех в мой проект, не так ли?

Это также означает, что все они должны быть отправлены моим клиентам. Настройки в конфигурации будут диктоваться только классом, который я буду использовать для инициализации члена двигателя.

OR

Я мог бы скомпилировать каждый из этих движков под одним и тем же именем. Импортируйте только одну DLL в моем основном проекте, и этот конкретный движок будет использоваться все время. Это лишило бы моих клиентов возможности использовать наше приложение для нескольких своих клиентов. Если только они не были готовы вручную переключать dll. Тьфу

Есть предложения?

РЕДАКТИРОВАТЬ # 2: На данный момент, видя мои варианты, я также мог бы сделать одну большую dll, содержащую базовый движок, а также все дочерние и мою конфигурацию, чтобы пользователь мог выбрать. Вместо того, чтобы ссылаться на несколько DLL и отправлять их все. Просто имейте один огромный и отправьте / ссылку, только один. Мне это тоже не очень нравится, так как это означает, что нужно доставлять одну большую dll всем моим клиентам, а не одну или две маленьких, которые соответствуют потребностям. Это все еще лучшее решение, которое я придумала.

Я все еще ищу лучшие предложения или ответы на мой оригинальный вопрос. Спасибо.

Ответы [ 2 ]

2 голосов
/ 14 мая 2009

Используйте отдельные библиотеки 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(); }

Теперь в вашем основном проекте просто загрузите интересующую вас 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();

Имя экспортируемой функции, вероятно, будет искажено, так что вы можете использовать файлы DEF или extern "C" в своих DLL, также не забудьте проверить на наличие ошибок.

0 голосов
/ 22 мая 2009

Я пришел к следующему решению:

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.

...