문제

저는 현재 여러 클라이언트에 대해 유사한 목적을 제공하지만 피드되는 데이터를 처리하는 방법에 대한 조정이 필요한 애플리케이션을 작성 중입니다.본질적으로 동일한 목적을 수행하지만 데이터를 완전히 다르게 전달합니다.

그래서 나는 다음과 같이 선언하기로 결정했습니다.-모든 방식의 공통 기능을 보유하고 다양한 엔진이 동일한 방식으로 응답하도록 보장하는 기본 인터페이스를 제공하는 공통 엔진 라이브러리를 만듭니다.-각 기능 방식에 맞는 특정 엔진을 작성합니다....각 엔진은 자체 .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을 모든 고객에게 배송한다는 것을 의미하기 때문에 이것을 별로 좋아하지 않습니다.그래도 이것이 제가 생각해낸 최고의 솔루션입니다.

나는 여전히 원래 질문에 대한 더 나은 제안이나 답변을 찾고 있습니다.감사해요.

도움이 되었습니까?

해결책 2

내가 찾은 해결책은 다음과 같습니다.

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

나는 Daniel의 답변과 그의 답변에 대한 의견을 사용했습니다.추가 조사 끝에 LoadFrom 메서드를 발견했습니다.

다른 팁

각 엔진마다 별도의 DLL을 사용하고 사용 로드라이브러리 기본 프로젝트에서 구성에 따라 특정 엔진을 로드합니다.

모든 엔진이 파생되는 공통 헤더 파일에 엔진 인터페이스를 두고 이 인터페이스는 기본 프로젝트에서도 사용됩니다.

다음과 같이 보일 수 있습니다:

// 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을 로드한 다음 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 파일을 사용하거나 DLL에서 extern "C"를 사용할 수 있으며 오류를 확인하는 것도 잊지 마세요.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top