인제 태터툴즈 날아간거 복구 했는데 .. 흠.. 쓸 말이 없네 ㅎㅎ
암턴 인제 글 써지니 모은거 써봐야지 -_- 텍스트 큐브로 업글 해봐 -_-;;
RTTI는 Run-Time Type Information의 약자로써, 실행시간에 객체의 타입 정보를 얻게 하는 C++의 확장? 정도 이다.
자바나 C#의 경우에는 리플렉션의 축소판 정도라고 생각하면 되겠다.
우선은 RTTI를 위하여 구현해야 하는 기능을 보자.
- 실행 시에 알려지지 않은 클래스의 이름과 크기를 얻을 수 있어야 한다.
- 실행 시에 알려지지 않은 클래스를 동적으로 생성할 수 있어야 한다.
우선 실행 시에 클래스의 이름을 얻는 방법부터 보자.
이를 위해서는 딱 두가지의 처리만 해주면 된다.
1. 자신의 클래스의 이름을 저장하는 정적변수를 만든다.
2. 그 이름을 리턴하는 GetClassName()을 오버라이드(override)한다.
소스로 보는 것이 더 확실할 것이다.
class CObject {
public:
// 자신의 클래스이름을 반환하는 메서드를 만든다.
virtual char* GetClassName() const { return NULL; }
};
class CSomeObject : public CObject {
public:
// 자신의 클래스 이름을 반환하는 메서드를 오버라이드한다.
virtual char* GetClassName() const { return lpszClassName; }
// 자신의 클래스의 이름을 저장하는 정적변수를 만든다.
static char lpszClassName[];
};
char CSomeObject::lpszClassName[] = "CSomeObject";
void main() {
// 사용하는 방법.
CObject *p;
p = new CSomeObject;
cout << p->GetClassName(); // 동적으로 만들어진
// 클래스의 이름을 알 수 있다!!
delete p;
}
실행결과는 다음과 같을 것이다.
CSomeObject
이것을 매크로로 정의하여 편하게 사용하여 보자.
그 매크로는 바로 두구두구두구두구!!!!
DECLARE_CLASSNAME(s)
IMPLEMENT_CLASSNAME(s)
위의 두 매크로들이다.
선언은 아래와 같이 되어있다.
#define DECLARE_CLASSNAME(s) static char lpszClassName[]
#define IMPLEMENT_CLASSNAME(s) char s##::lpszClassName=(#s)
간단하게 사용하는 예제를 적어본다.
(위의 예제와 똑같은 것이므로 주석은 안 달았다.)
class CObject {
public:
virtual char* GetClassName() const { return NULL; }
};
class CSomeObject : public CObject {
public:
DECLARE_CLASSNAME(CSomeObject);
virtual char* GetClassName() const { return lpszClassName; }
};
IMPLEMENT_CLASSNAME(s);
void main() {
CObject *p;
p = new CSomeObject;
cout << p->GetClassName();
delete p;
}
이제 실행 시에 클래스의 이름을 알아내는 방법은 알았다.
책에서는 저렇게 하였으나, 개인적인 생각으로는
DECLARE_CLASSNAME(s) 매크로를
#define DECLARE_CLASSNAME(s) static char lpszClassName[];
virtual char* GetClassName() const { return lpszClassName; }
으로 하는 것이 나을 꺼 같다.
-------------------------------------------------------------------------------
이제 동적 생성을 지원하기 위한 조건을 알아보도록 하겠습니다.
우선 동적 생성을 지원하는 클래스를 만들기 위해서
코드 자동 생성기가 해야 하는 작업을 구체적으로 살펴보면,
1. 객체의 클래스 이름을 알 수 있어야 되며,
2. 객체의 크기를 알 수 있어야 되며,
3. 클래스를 동적으로 생성하기 위한 함수를 갖어야 한다.
위의 작업이 가능하도록 구조체를 만들어 봅니다.
struct CRuntimeClass {
char m_lpszClassName[21]; // 객체의 클래스 이름
int m_nObjectSize; // 객체의 크기
CObject* (*pfnCreateObject)(); // 실제 객체를 생성하기 위한 함수 포인터
CObject* CreateObject; // 객체를 생성하기 위한 함수(인터페이스)
};
// 단순히 pfnObject 함수포인터를 랩핑(wrapping)한다.
CObject* CRuntimeClass::CreateObject() { return (*pfnObject)(); }
이제 문제는 자신을 동적으로 생성하는 코드를 어떤 방식으로 준비하느냐 하는 것이다.
해답은 정적(static) 맴버 함수를 이용하는 것이다.
(객체가 만들어지기 전에 이미 메모리상에 존재하므로 가능하게 된다.)
그럼 CObject를 고쳐보자.
class CObject {
virtual CRuntimeClass* GetRuntimeClass() const { return NULL; }
static CRuntimeClass classObject;
virtual ~CObject() { }
protected:
CObject() { printf("CObject constructor\n"); }
};
CRuntimeClass CObject::classObject = { "CObject", sizeof(CObject), NULL };
그리고 실제로 상속받아서 클래스를 구현하는 경우를 살펴보자.
class CAlpha : public CObject {
public:
virtual CRuntimeClass* GetRuntimeClass() const { return &classCAlpha; }
static CRuntimeClass classCAlpha;
static CObject* CreateObject();
protected:
CAlpha() { printf("CAlpha constructor\n"); }
};
CRuntimeClass CAlpha::classCAlpha = { "CAlpha", sizeof(CAlpha), CAlpha::CreateObject };
CObject* CAlpha::CreateObject() { return new CAlpha; /* 자신을 동적으로 생성한다. */ }
이제 이것을 어떻게 쓰는지만 알면 해결이다.
#define RUNTIME_CLASS(class_name) (&class_name::class##class_name)
void main(void) {
CRuntimeClass* pRTCAlpha = RUNTIME_CLASS(CAlpha);
// CRuntimeClass* pRTCAlpha = &CAlpha::classCAlpha;
CObject* pObj1;
pObj1 = pRTCAlpha->CreateObject();
printf("CAlpha class=%s\n", pObj1->GetRuntimeClass()->m_lpszClassName);
delete pObj1;
}
실제로 MFC에서는 매크로로 만들어서 사용하고 있다. (afx.h에 있다.)
#define DECLARE_DYNAMIC(class_name) static CRuntimeClass class##class_name
#define IMPLEMENT_DYNAMIC(class_name) CRuntimeClass \
class_name::class##class_name = { \
(#class_name), \
sizeof(class_name), \
class_name::CreateObject };
#define DECLARE_DYNCREATE(class_name) static CObject* CreateObject();
#define IMPLEMENT_DYNCREATE(class_name) CObject* \
class_name::CreateObject() { \
return new class_name; \
}
그럼 마지막으로 매크로를 이용해서 종합해보자.
class CAlpha : public CObject {
public:
virtual CRuntimeClass* GetRuntimeClass() const { return &classCAlpha; }
DECLARE_DYNAMIC(CAlpha);
DECLARE_DYNCREATE(CAlpha);
protected:
CAlpha() { printf("CAlpha constructor\n"); }
};
IMPLEMENT_DYNAMIC(CAlpha);
IMPLEMENT_DYNCREATE(CAlpha);
class CBeta : public CObject {
public:
virtual CRuntimeClass* GetRuntimeClass() const { return &classCBeta; }
DECLARE_DYNAMIC(CBeta);
DECLARE_DYNCREATE(CBeta);
protected:
CBeta() { printf("CBeta constructor\n");
};
IMPLEMENT_DYNAMIC(CBeta);
IMPLEMENT_DYNCREATE(CBeta);
void main() {
// Create CAlpha class
CRuntimeClass *pRTCAlpha = RUNTIME_CLASS(CAlpha);
CObject *pObj1;
pObj1 = pRTCAlpha->CreateObject();
printf("CAlpha class=%s\n", pObj1->GetRuntimeClass()->m_lpszClassName);
// Create CBeta class
CRuntimeClass* pRTCBeta = RUNTIME_CLASS(CBeta);
CObject *pObj2;
pObj2 = pRTCBeta->CreateObject();
printf("CBeta class=%s\n", pObj2->GetRuntimeClass()->m_lpszClassName);
delete pObj1;
delete pObj2;
}
출처 : http://rhio.tistory.com/5
다중 터미널 입력기 일꾼 v 0.0.3
사용 툴 : VS 2003
1. 사용 가능 터미널
- 테라텀
- XShell(2.0, 3.0)
- PineTerm
- CRT, SecureCRT
- Putty(텔넷, SSH는 테스트 안해봤음)
2. 한글은 입력되지 않습니다.
3. 붙여 넣기는 버튼을 이용하시면 됩니다.
4. 프로그램을 실행하시고 찾기를 누르면 터미널에 등록 되고 표시 됩니다.
5. 최소화한 터미널 창은 입력되지 않습니다.
Histroy
수정 사항 (v 0.0.3)
- 붙여넣기가 최소화일때만 적용 되는 것 정상 작동하도록 수정
수정 사항 (v 0.0.2)
- Putty 터미널 못 찾는 버그 수정
- ESC 입력 가능
- 탭 입력 가능
- 항상 위 기능 및 버튼 추가
- 최소화 화면 입력 막기 버그 수정
-------- SELINUX 의 정책이 문제이군요
# setsebool -P ftp_home_dir 1
페도라 코어 4 까실때 SELinux 로 설정했다면 디폴트로 사용자의 home 디렉토리에 쓰기를 막아놓는다.
SELinux 설정에서 FTP 부분을 변경하자.
# service vsftpd restart
home 디렉토리의 읽고쓰기를 1(True)로 변경하시고 vsftpd 를 재시작.
# setsebool -P ftpd_disable_trans 1
FTP 에 관하여 SELinux 정책을 아예 적용하지 않는 옵션을 설정
"500 oops: cannot change directory"
Trying to ftp in to a Fedora Core 5 box using a local username. Password is accepted, but the connection is then closed with this error message.
This is because of SELinux's policies. To fix it, issue (as root):
setsebool -P ftp_home_dir=1
The -P flag ensures the value is saved after reboot.
------------------------------------------------------------------------------
ftp 정상적인 세팅 상태에서 로그인 후
500 OOPS: cannot change directory
와 같은 메세지가 출력되며 접속이 끊어질 경우 다음과 같이 하면 됩니다.
/etc/selinux/config 에서
SELINUX=permissive
와 같이 바꾸면 됩니다. SELINUX의 Deny를 permissive로..
즉 메세지만 로그에 남기고 접근을 허용하는 것이지요.
enforcing이 기본인데 이것은 접근을 차단하는 것입니다.
출처 : http://breathair.tistory.com/8