2011-07-05 2 views
1

나는 C++ 프레임 워크를 작성하는 데 문제가있어 사용자가 사용하는 것보다 오버 헤드가 적어야합니다. 사용자는 프레임 워크의 BaseClass에서 파생 된 클래스가 포함 된 공유 라이브러리를 만들고 인스턴스의 파생 클래스를 반환하기 위해 extern "C"createInstance() - 메서드를 구현하여 프레임 워크에 자신의 작업을 게시 할 수 있습니다. 따라서 프레임 워크는 dlsym()을 사용하여 공유 라이브러리를 통해 createInstance-Method를 호출하여 사용자 클래스에 액세스 할 수 있습니다. 프레임 워크에서C++ 팩토리 패턴 : 명시 적 createInstance() 생성 - 메서드 자동으로

class BaseClass{} 
class UserClass : public BaseClass{} 

extern "C"{ 
    BaseClass* UserXcreateInstance(){ 
    return new UserClass(); 
    }       
} 

:

typedef BaseClass* (*CreateInstance)(); 
void* handle; 
CreateInstance createInstance; 
handle = dlopen("libUserLibrary.so", RTLD_LAZY | RTLD_GLOBAL); 
createInstance = reinterpret_cast <CreateInstance*> dlsym(handle, "UserXcreateInstance"); 
BaseClass* userX = createInstance(); 

내 질문 : 그것은 UserXcreateInstance() 생성 가능 - 것으로에게이 돈`t 사용자가 생각하는, 그래서 각 사용자 라이브러리에서 중복 방법을, 그것에 대해?

또 다른 방법은, 내가 직접를 통해 사용자 클래스의 생성자를 호출한다 생각했다 ...

가 나는 템플릿 + 매크로 수있을 것이라고 생각하지만 난 아직이 작업을 수행 할 수있는 방법을 발견하지 않았습니다 dlsym 및 적절한 이름 mangling. (나는 설정 파일에서 어떤 공간 + 클래스 이름을 알고)하지만 특히 생성자 호출은 일반 함수 호출과 동일하지만 매우 재미없는이에게 적절한 솔루션을 생각 말게

답변

4

사용자의 부분별로 코딩하지 않고도 자동으로 생성하는 방법을 상상할 수 없습니다.

OBJECT_CREATOR(UserClass); 
+0

은 한 줄이 네보다 낫다 주셔서 감사합니다;) – Dudero

+0

당신은 환영합니다! – bcsanches

3

내가 dlsym이를 통해 사용자 함수를 호출 가정합니다 :

#define OBJECT_CREATOR(X) \ 
    extern "C" {   \ 
     BaseClass *UserXCreateInstance() {\ 
      return new X(); \ 
     }\ 
    } 

그리고 사용자 그의 CPP 파일에 둘 필요가 : 나는 아마도 매크로를 사용하여 간단하게 할 수있는 방법을 상상할 수 절대적인 요구 사항은 아닙니다.

CRTP을 사용하여 원하는 것을 쉽게 얻을 수 있습니다. 그런 다음 정적 도우미 객체의 생성자가 관련 데이터를 중앙 저장소에 등록합니다. 그것은 다음과 같이 가야한다 :

template <typename UserClass> 
class BaseClass 
{ 
    private: 
    class UserObjectFactory 
    { 
     UserObjectFactory() 
     { 
     std::string myname = typeid(UserClass).name(); 
     CentralObjectFactory::instance()->register(this, myname); 
     } 
     BaseClass* XUserCreateInstance() 
     { 
     return new UserClass; 
     }    
    }; 
    static UserObjectFactory factory; 
}; 

사용자 코드는 간단하다 :

class MyClass : public BaseClass<MyClass> 
{ 
    // whatever 
}; 

은 아마의 CentralObjectFactory 인스턴스는 std::string에서 UserObjectFactory에 (멀티)지도의 어떤 종류가 포함되어 있습니다.

mynametypeid(UserClass).name() 대신 고유하게 생성 된 문자열로 초기화되어 충돌을 피할 수 있습니다.

각 사용자의 클래스 중 하나의 개체 만 필요한 경우 UserObjectFactoryUserClass의 인스턴스로 만들고 대신 등록 할 수 있습니다.

std::string myname = typeid(UserClass).name(); 
    CentralObjectRepository::instance()->register(XUserCreateInstance(), myname); 

이 디자인이 사용자의 요구 사항을 충족합니까?

+0

당신의 아이디어는 매우 재미 있지만, 그것은 나를 위해 일하지 않습니다. 달성되지 않는 정적 헬퍼 클래스의 생성자는 ...이 사용자의 공유 라이브러리의 dlopen을 호출에 의해 발생 이상의 전제 조건이있다 하는가? – Dudero

+0

어 - 오, 정말 죄송합니다. 실제로 작동하지 않습니다. 내가 고칠 수 있으면 알려주지. –