Static Library 제작시 Name Conflict 피하기 ( C2084 )
MYDN2008. 10. 21. 15:29
namespace 에 대해 오해하고 있는 소수의 분들을 위해...
Static Library 를 제작하고, 또 사용하다보면 Name Conflict 에러가 발생하는 경우가 있습니다.
이 에러는 프로젝트에 포함된 이종 라이브러리가 같은 이름의 함수명/변수명을 갖게 될 경우 나타납니다.
가령, 프로젝트에서 a.lib , b.lib 두개의 라이브러리를 link 할때에
a.lib 에서 fnA() 라는 함수가 선언되어있고,
b.lib 에서 fnA() 라는 함수가 선언되어있는 경우
두 함수의 이름이 같기 때문에 발생하는 에러입니다.
이 때 conflict 를 피하기 위하여 생긴것이 namespace 입니다.
namespace 는 내부에 정의된 이름들에 대해 마치 class의 캡슐화와 같은 효과를 줍니다.
.net 프로그래밍을 하셨다면,
using namespace std;
라는 구문을 보셨을텐데요,이 명령은
소스코드 내에서 cout 등의 함수들을 호출할때
std::cout 을 호출하는것으로 인식하게 해 줍니다.
즉, 표준 함수의 namespace 가 std 인 셈입니다.
개발을 하다보면,
동일 소스를 사용해서 이종 Static Library 를 생산해야할 때가 있습니다.
이럴때에는 소스가 동일하기 때문에 똑같은 이름의 함수/변수를 갖는 Static Library 가 생기게 됩니다.
( 물론 소스를 복사해서 쓸수도 있지만, 동일 소스가 여러개로 보관되면 관리상의 치명적인 문제점이 생기게 되겠죠 )
이럴때, 프로젝트를 기준으로 하여
소스가 동일하더라도, 프로젝트별 namespace 를 달리하게 되면
하나의 코드로 여러개의 library 를 만들더라도 conflict 문제 없이 빌드할 수 있습니다.
일반적으로 namespace 를 사용하는 소스의 예는 다음과 같습니다.
using namespace myprojectns;
namespace myprojectns{
}
namespace myprojectns{
int g_nCount;
void fnA(){
Sleep(0);
}
}
마치 Class 와 비슷한 모양을 갖게 되는데요
위의 예에서는 myprojectns 로 설정된 네임스페이스 내에
직접 코딩을 하게 되면 외부의 소스에서는 접근할때에 ( extern 되어있다고 가정 )
myprojectns::g_nCount
myprojectns::fnA()
로 접근 할 수 있습니다.
다음은 이를 간단히 적용하기 위한 매크로 입니다.
// MyNamespace.h
#pragma once
#pragma once
#if defined(_LIB_SDK_PROJECT_Y)
#define MYNAMESPACE MYNAMESPACE_LIB_PROJECT_Y
#elif defined(_LIB_SDK_PROJECT_Z)
#define MYNAMESPACE MYNAMESPACE_LIB_PROJECT_Z
#else
#error MYNAMESPACE Required. Check MyNamespace.h
#endif
#define MYNAMESPACE MYNAMESPACE_LIB_PROJECT_Y
#elif defined(_LIB_SDK_PROJECT_Z)
#define MYNAMESPACE MYNAMESPACE_LIB_PROJECT_Z
#else
#error MYNAMESPACE Required. Check MyNamespace.h
#endif
#define MN MYNAMESPACE
#define _START_OF_INTERNAL_SRC namespace MYNAMESPACE {using namespace MYNAMESPACE ;
#define _END_OF_INTERNAL_SRC }
#define _SO_INTERNAL_SRC _START_OF_INTERNAL_SRC
#define _EO_INTERNAL_SRC _END_OF_INTERNAL_SRC
#define _EO_INTERNAL_SRC _END_OF_INTERNAL_SRC
_LIB_SDK_PROJECT_Y 는 Project의 Properties 에서 설정한 Preprocessor definitions 입니다.
Project별로 다른 정의를 주어야하는 부분입니다.
위의 매크로는 Preprocessor definitions 에서 프로젝트 특성을 읽어
서로 다른 namespace 를 적용할 수 있도록 해줍니다.
예에서는 Preprocessor definitions 가
_LIB_SDK_PROJECT_Y 인경우 MYNAMESPACE_LIB_PROJECT_Y
_LIB_SDK_PROJECT_Z 인경우 MYNAMESPACE_LIB_PROJECT_Z
의 namespace 가 정의됩니다.
cpp 소스에서의 사용은 다음과 같습니다.
// _LIB_SDK_PROJECT_Y 의 소스일 때
#include <stdio.h>
#include "MyNamespace.h"
_SO_INTERNAL_SRC
VOID fnA()
{
#include <stdio.h>
#include "MyNamespace.h"
_SO_INTERNAL_SRC
VOID fnA()
{
...
}
BOOL fnB()
{
BOOL fnB()
{
...
}
_EO_INTERNAL_SRC
_EO_INTERNAL_SRC
헤더파일을 포함하고, 소스의 위 아래를 _SO_ , _EO_ 매크로로 감싸주면
헤더에 정의된 namespace 가 project 별로 적용됩니다.
외부에서 위 소스의 함수를 호출하고자 할때에는 다음과 같이 호출할 수 있습니다.
//_LIB_SDK_PROJECT_Y 라이브러리를 링크했을 때
#include <stdio.h>
void initialEntry()
{
}
#include <stdio.h>
void initialEntry()
{
MYNAMESPACE_LIB_PROJECT_Y::fnA();
MYNAMESPACE_LIB_PROJECT_Y::fnB();
MYNAMESPACE_LIB_PROJECT_Y::fnB();
}
혹은,
//_LIB_SDK_PROJECT_Y 라이브러리를 링크했을 때
#include <stdio.h>
using namespace MYNAMESPACE_LIB_PROJECT_Y;
void initialEntry()
{
}
#include <stdio.h>
using namespace MYNAMESPACE_LIB_PROJECT_Y;
void initialEntry()
{
fnA();
fnB();
fnB();
}
외부 library 제작이 필요없는 실행파일 기반 프로젝트이거나
소형 프로젝트일 경우에는 namespace를 사용하지 않아도 될것 같습니다.
하지만, 여러명이 작업하는 프로젝트이거나 ( 소스별 extern function name conflict 문제 )
static library 를 만드는 프로젝트일 경우에는
사용할 필요성이 높아 보이는 부분입니다.
-------------------------------------------------------------------------------------------
덧붙혀서,
매크로를 자세히 보신 분은 MYNAMESPACE 가 MN 으로 정의된걸 보셨을텐데요
이는 내부에서의 사용편의성을 위한 정의입니다.
가령, 배포용 라이브러리를 제작할때에
내부소스에서 사용되는 함수/변수들은 namespace를 주고,
extern 되는 함수에 대해서는
(사용편의성을 위해) namespace없이 unique한 이름으로 정의하는 경우
내부에서 사용되는 소스의 경우 _SO_, _EO_ 매크로를 사용하고,
외부에 extern 되는 소스는 _SO_, _EO_ 매크로의 사용없이
MN::fnA() 등과 같이 바로 접근할 수 있도록 정의한 부분입니다.
가령,
// extern source
#include <stdio.h>
#include "MyNamespace.h"
extern "C" void fnProjectInit()
{
#include <stdio.h>
#include "MyNamespace.h"
extern "C" void fnProjectInit()
{
MN::fnA();
}
( extern의 위치는 이해의 편의를 위해... )
lib 제작시 외부에 제공되는 함수는 위의 모습처럼 _SO_, _EO_ 없이 사용하고,
내부에서 다른소스의 함수를 가져다 쓰는 형태를 만들어주면,
외부에서는 namespace 없이 fnProjectInit()을 바로 호출할 수 있고,
소스의 내부에 정의된 함수나 변수이름등은 중복확률이 낮아지게 되는 효과를 갖게 됩니다.
USB/Flash Memory 로 Windows Vista Boot 설치 하기
MYDN2008. 10. 7. 11:11
원문 : http://www.techmixer.com/install-windows-vista-from-bootable-usb-flash-memory-drive/
Create a bootable Windows Vista on Flash Memory
1. Flash memory drive 를 FAT32 file system 으로 포멧
Windows Vista 가 설치된 PC에서 CMD.EXE 를 실행하여 다음의 명령어를 수행합니다.
( 아래는 USB 드라이브가 "disk 1" 인 경우입니다. 사전에 "list disk" 명령어를 사용하여, USB 의 장치 번호를 반드시 확인하세요 )
- diskpart
- select disk 1
- clean
- create partition primary
- select partition 1
- active
- format fs=fat32
- assign
- exit
2. Vista DVD 를 Flash Drive 로 복사
아래의 명령어를 사용하여, 비스타 DVD를 플래시 드라이브로 복사합니다. ( 비스타를 d: , USB가 e: 드라이브인 경우의 예 )
- xcopy d:\*.* /s/e/f e:\
3. BIOS 설정에서 USB Drive 로 부팅을 설정
4. USB flash memory drive 로 부팅하여, Vista 를 설치
phpicalendar - Mac/Windows 가 호환되는 Web일정관리
APM++2008. 9. 24. 11:17
아웃룩으로 일정관리를 해왔는데,
하루에 수십통씩 메일이 오다보니
메일 저장 공간을 1년마다 분리해줘야 하는 불편함이 있었다.
( 분리를 하지 않으면 1Gb 가 넘는 저장공간에 느려지고 멈추고 막 그런다 아웃룩... )
다음으로, 구글으로 일정관리를 하려 했으나,
내 일정은 괜찮겠지만, 회사 일정이 타사의 DB에서 관리된다는
보안상의 취약점이 있어 포기해야했다.
그래서 찾게된 것이
ical 을 지원하는 웹베이스의 일정관리 프로그램 phpicalendar 되겠다.
ical 은 애플에서 지원되는 캘린더인데,
많이 유명한가보다.
아웃룩에서도 지원이되고, 구글 캘린더, 무슨 캘린더, 저런 캘린더 왠만한 캘린더에서는 다 지원한다.
이것이 가장 큰 장점.
즉, phpicalendar 를 사용하면,
자신의 서버에 ical 형식의 데이터를 두어,
웹에서 일정을 볼 수 있고,
사용자는 자신이 사용하기 편한 툴을 사용하여 일정을 갱신하면 된다.
다음은 지금 구축하고 있는 일정관리의 진행.
phpicalendar 를 설치하고 주의 일정을 웹상에 게시한 화면이다.
ical이 공유된 상태에서 자동으로 갱신된다.
ical 을 관리하고 공유하기 위해 사용하는 툴로는
windows calendar 를 사용하고 있다.
vista 에서 기본제공되는 프로그램으로
기능은 오피스보다 떨어지지만,
오피스보다 가볍다는 장점 하나만으로... 쓰고있다...
일단, 더 봐야하겠지만
ical은 플랫폼의 특성을 타지 않고 사용할 수 있다는
장점. 그 확장성으로 진행에 무리는 없을것 같다.
http://phpicalendar.net/
phpicalendar 의 event 항목에서 한글이 깨져 보일때 처리법
APM++2008. 9. 23. 15:32
환경 :
WindowsServer 2003
Apache 2.x
WebDav모듈사용.
phpicalendar 2.24 설치
phpicalendar 2.24를 설치하고
한글테스트를 진행하였는데,
메인화면에서는 잘 표시되는 한글이
이벤트를 클릭하면 깨져서 표시된다.
이벤트를 출력해주는 소스파일은 다음과 같다
/phpcalendar2.24/includes/event.php
에디트 툴을 이용해서
해당 파일을 열고
위의 문장을 찾아 붉은색 부분을 삭제해 준다
이처럼 수정하고, 저장후에
이벤트를 확인하면
한글이 정상적으로 출력되는것을 볼 수 있다.
WindowsServer 2003
Apache 2.x
WebDav모듈사용.
phpicalendar 2.24 설치
phpicalendar 2.24를 설치하고
한글테스트를 진행하였는데,
메인화면에서는 잘 표시되는 한글이
이벤트를 클릭하면 깨져서 표시된다.
이벤트를 출력해주는 소스파일은 다음과 같다
/phpcalendar2.24/includes/event.php
에디트 툴을 이용해서
해당 파일을 열고
$event['description'] = stripslashes(utf8_decode(urldecode($event['description'])));
$event['event_text'] = stripslashes(utf8_decode(urldecode($event['event_text'])));
$event['location'] = stripslashes(utf8_decode(urldecode($event['location'])));
$event['event_text'] = stripslashes(utf8_decode(urldecode($event['event_text'])));
$event['location'] = stripslashes(utf8_decode(urldecode($event['location'])));
위의 문장을 찾아 붉은색 부분을 삭제해 준다
$event['description'] = stripslashes((urldecode($event['description'])));
$event['event_text'] = stripslashes((urldecode($event['event_text'])));
$event['location'] = stripslashes((urldecode($event['location'])));
$event['event_text'] = stripslashes((urldecode($event['event_text'])));
$event['location'] = stripslashes((urldecode($event['location'])));
이처럼 수정하고, 저장후에
이벤트를 확인하면
한글이 정상적으로 출력되는것을 볼 수 있다.