Jan 24
alonesProgramming/C/C plus plus FILETIME, FileTimeToSystemTime, getimeofday in windows, GetSystemTimeAsFileTime, gettimeofday, SYSTEMITM, UTC to EPOCH, 시간, 시간 측정, 현재 시간 구하기
getimeofday()를 windows에서도 아래와 같이 구현해서 사용할 수 있고 또 그 것을 이용해서 코드의 수행 시간을 microsecond까지 측정할 수 있다.
최신 내용은 아래 wiki를 참조
in my wiki: http://alones.byus.net/moniwiki/wiki.php/c_cpp_windows_tip_gettimeofday?action=show
- initial version: 2007.06.03
OpenAsthra의 글들을 참고로 해서 작성하였다.
목차
-
- 1 gettimeofday in linux
- 2 gettimeofday in windows
-
- 2.1 Approach to gettimeofday in windows
- 2.2 code of gettimeofday in windows
- 2.3 usage of gettimeofday in windows
- 3 gettimeofday를 이용한 실행 시간 구하기
- 4 gettimeofday와 이 것을 이용한 전체 코드
- 5 References
1 gettimeofday in linux #
gettimeofday()는 아래 signature와 값이 system의 현재 시간을 가지고 온다.
#include <sys/time.h>
#include <unistd.h>
int gettimeofday(struct timeval *tv, struct timezone *tz);
//
첫 번째 인자는 다음과 같이 seconds와 microseconds를 가지고 있다. 즉, 현재 시간을 초와 마이크로초로 알 수 있는 유용한 api이다.
struct timeval
{
long tv_sec; // 초
long tv_usec; // 마이크로초
}
//
그리고 두 번째 인자는 쓰이지 않으면 NULL을 던져 주면 될 것이다.
2 gettimeofday in windows #
2.1 Approach to gettimeofday in windows #
Windows에는 gettimeofday()가 없다. 하지만
GetSystemTimeAsFileTime()을 이용해서 gettimeofday()를 만들 수 있다.
GetSystemTimeAsFileTime()은 다음과 같은 Signature를 가지고 현재 system의 date와 time을 Universal Time (UTC) format으로 반환해준다.
VOID GetSystemTimeAsFileTime(
LPFILETIME lpSystemTimeAsFileTime // file time
);
//
out parameter는 FILETIME struct로 다음과 같이 32bit 하위 bit와 32bit 상위 bit를 가지고 있다. 시간은 64bit 값으로 100 nanosecond단위이다.
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *PFILETIME;
//
이 것을
FileTimeToSystemTime()을 이용해서 SYSTEMTIME으로 변경해서 사용하기도 할 것이다.
아무튼 windows에서 gettimeofday()를 만들기 위해서 우리는 다음과 같은 step을 따르면 될 것이다.
- GetSystemTimeAsFileTime()으로 system time을 구한다.
- 구한 시간인 FILETIME을 64bit로 합친다. (unsigned __int64)
- UNIX EPOCH time으로 변환한다. (웹을 검색해보면 쉽게 상수를 찾을 수 있다)
- 100nao를 micro로 변환하기 위해서 10을 나누어준다.
- second와 microsecond로 변환한다.
2.2 code of gettimeofday in windows #
위의 approach를 따른 코드는 다음과 같다.
#include < time.h >
// epoch time으로 변환할 상수
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
#else
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
#endif
// for timezone
struct timezone
{
int tz_minuteswest; /* minutes W of Greenwich */
int tz_dsttime; /* type of dst correction */
};
// gettimeofday in windows
int gettimeofday(struct timeval *tv, struct timezone *tz)
{
FILETIME ft;
unsigned __int64 tmpres = 0;
static int tzflag;
if (NULL != tv)
{
// system time을 구하기
GetSystemTimeAsFileTime(&ft);
// unsigned 64 bit로 만들기
tmpres |= ft.dwHighDateTime;
tmpres <<= 32;
tmpres |= ft.dwLowDateTime;
// 100nano를 1micro로 변환하기
tmpres /= 10;
// epoch time으로 변환하기
tmpres -= DELTA_EPOCH_IN_MICROSECS;
// sec와 micorsec으로 맞추기
tv->tv_sec = (tmpres / 1000000UL);
tv->tv_usec = (tmpres % 1000000UL);
}
// timezone 처리
if (NULL != tz)
{
if (!tzflag)
{
_tzset();
tzflag++;
}
tz->tz_minuteswest = _timezone / 60;
tz->tz_dsttime = _daylight;
}
return 0;
}
//
2.3 usage of gettimeofday in windows #
gettimeofday()는 아래와 같이 사용할 수 있을 것이다.
struct timeval now;
gettimeofday(&now, NULL);
printf("time: %ld sec %ld msec\n", now.tv_sec, now.tv_usec);
//
3 gettimeofday를 이용한 실행 시간 구하기 #
우리는 gettimeofday를 이용해서 코드의 수행 시간을 microsecond까지 측정할 수 있는 다음 함수를 만들 수 있을 것이다.
// 시간 측정
// event 1은 측정 시작
// event 2는 측정 완료 & print
void log_time(int event)
{
static struct timeval tv_start;
struct timeval tv_end;
struct timeval *tv;
tv = ((event==2)?&tv_end:&tv_start);
gettimeofday(tv, NULL);
if(event==2)
{
printf("Time: %ld Seconds %ld Microseconds\n",
tv_end.tv_sec - tv_start.tv_sec,
tv_end.tv_usec - tv_start.tv_usec);
}
}
//
4 gettimeofday와 이 것을 이용한 전체 코드 #
#include < time.h >
#include <windows.h>
#include <iostream>
#include <stdio.h>
// epoch time으로 변환할 상수
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
#else
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
#endif
// for timezone
struct timezone
{
int tz_minuteswest; /* minutes W of Greenwich */
int tz_dsttime; /* type of dst correction */
};
// gettimeofday in windows
int gettimeofday(struct timeval *tv, struct timezone *tz)
{
FILETIME ft;
unsigned __int64 tmpres = 0;
static int tzflag;
if (NULL != tv)
{
// system time을 구하기
GetSystemTimeAsFileTime(&ft);
// unsigned 64 bit로 만들기
tmpres |= ft.dwHighDateTime;
tmpres <<= 32;
tmpres |= ft.dwLowDateTime;
// epoch time으로 변환하기
tmpres -= DELTA_EPOCH_IN_MICROSECS;
// 100nano를 1micro로 변환하기
tmpres /= 10;
// sec와 micorsec으로 맞추기
tv->tv_sec = (tmpres / 1000000UL);
tv->tv_usec = (tmpres % 1000000UL);
}
// timezone 처리
if (NULL != tz)
{
if (!tzflag)
{
_tzset();
tzflag++;
}
tz->tz_minuteswest = _timezone / 60;
tz->tz_dsttime = _daylight;
}
return 0;
}
// 시간 측정
// event 1은 측정 시작
// event 2는 측정 완료 & print
void log_time(int event)
{
static struct timeval tv_start;
struct timeval tv_end;
struct timeval *tv;
tv = ((event==2)?&tv_end:&tv_start);
gettimeofday(tv, NULL);
if(event==2)
{
printf("Time: %ld Seconds %ld Microseconds\n",
tv_end.tv_sec - tv_start.tv_sec,
tv_end.tv_usec - tv_start.tv_usec);
}
}
void main()
{
// method 1. directly use gettimeofday
struct timeval now;
struct timeval now2;
gettimeofday(&now, NULL);
Sleep(100);
gettimeofday(&now2, NULL);
long elpase_sec = now2.tv_sec - now.tv_sec;
long elpase_usec = now2.tv_usec - now.tv_usec;
printf("elapse: %ld sec %ld msec\n",
elpase_sec, elpase_usec);
// method2. use log_time
log_time(1);
Sleep(1050);
log_time(2);
}
//
Jan 22
alonesOS & Tools doxygen, Doxygen 1.5.2, Doxygen 1.5.4, JavaDoc, 주석
최근 과제의 상세 설계서를 Doxygen으로 대체하면서 현재 기준 최신 Doxygen 버전인 1.5.4를 사용해서 예전에 1.5.2버전으로 작성한 가이드 문서를 업데이트해서 포스팅합니다.
변경 사항은 아래 2nd revision을 참고 하면 된다.
최신 내용은 아래 wiki에서 볼 수 있다.
in my wiki: http://alones.byus.net/moniwiki/wiki.php/tools_doxygen?action=show
- initial version: 2007.07.17
- 2nd revision: 2008.01.22
- 1.5.4에 따른 변경 내용 작성
- 한글 관련 내용 수정
- 그룹핑 기능 설명 추가
- 그래프와 다이어그램
목차
-
- 1 Doxygen 소개
- 2 Doxygen으로 코드를 문서화 하기
-
- 2.1 File
- 2.2 Class
- 2.3 Class 멤버 변수
- 2.4 Class 멤버 함수 또는 일반 함수
- 1.1 define이나 변수 선언
- 1.2 struct나 enum
- 2 그룹핑 (Grouping)
- 3 그래프와 다이어그램 그리기
-
- 3.1 Graphviz 설치
- 3.2 설정
- 4 Doxygen 설치
- 5 DoxyWizard로 간단하게 Doxygen 만들어 보기
-
- 5.1 Step1. Configuration
Doxygen
-
- 5.1.1 Wizard
- 5.1.2 Expert
- 5.1.3 Load…
- 5.2 Step2. Save the
configuration file
- 5.3 Step3. Specify the
directory from which to run doxygen
- 5.4 Step4. Run doxygen
- 6 chm (도움말) 파일 만들기
-
- 6.1 MS HTML Help 설치 확인
- 6.2 DoxyWizard 설정
- 7 Tips & Cautions
-
- 7.1 Config 파일 수정
- 7.2 Tree 보여주기
- 7.3 class의 protected나
private 보여주기
- 7.4 한글 보여주기 문제
- 8 References
1
Doxygen 소개 #
이 글을 쓰고 있는 시점의 버전이 1.5.4를 기준으로 설명한다. 예전에 사용하고 있던 것 보다 HTML도 이쁘고 wizard도
편리해진 것 같다. 예전엔 주로 Visual Studio 6.0의 플러그린 버전을 사용했었지만 IDE에 종속되는 느낌이 있어서 독립적인
Doxygen 프로그램을 사용하기로 했다.
Doxygen으로 코드를 문서화 하는 것에 대해서 간단히 설명하고 설치와 Doxygen 문서 생성, tip 등에 대해서 다루겠다.
※ Doxygen comment에 사용되는 special comment (e.g. @brief)에 대한 것은 References의
링크를 참고
2
Doxygen으로 코드를 문서화 하기 #
Doxygen으로 코드를 문서화 할 때 쓰는 방식은
JavaDoc, Qt, 두개의 c++ 주석 (i.e. ////) 등 여러
가지가 있고 또 이 것을 혼용해서 쓸 수도 있다. Doxygen 사이트의
Documenting the
Code 페이지를 보면 알 수 있다. 나 자신이 써온 것을 위에 것에서 찾으면
JavaDoc에 가까운 것 같다. (정확히 일치한지는 모르겠다)
헤더나 소스 파일에는 파일명과 간략한 설명, 저자, history 정도를 기술 해주면 될 것이다. 이 것의 예는 다음과 같다. (제
스타일 대로)
/**
* @file AloExcelAuto.h
* @brief CAloExcelAuto class
* @author alones
* @date initial version: 2007.07.18
* @date second revision: 2007.07.18
*/
class에는 class 명과 간략한 설명 정도를 기술하면 될 것이다.
/**
* @class CAloExcelAuto
* @brief excel automation class
*/
class CAloExcelAuto
2.3
Class 멤버 변수 #
다음과 같이 각 멤버 변수에 대해서 작성할 수 있을 것이다.
private:
long m_nFd; /**< fd for checking invalid*/
2.4
Class 멤버 함수 또는 일반 함수 #
함수에 대한 설명이나 in/out 파라미너, 리턴 값 정도와 참고할 함수 예제 코드 정도를 기술하면 될 것이다. 이에 대한 것들을
예제로 작성해보면 다음과 같을 것이다.
- @see의 경우는 함수만 있으면 함수 명을 쓰면 자동 링크 된다.
- @code ~ @endcoe 에 코드를 넣으면 된다.
- @addtogroup는 각 함수 등을 moudle로 묶어 주는 역할을 해준다. 실제 doxygen을 생성하면 tree에 Modules라는
부분이 추가되어있고 @addtogroup이 같은 항목들끼리 묶여져 있다.
/**
* @brief open excel file
* @param[in] strpath (std::string) excel path
* @param[out] nError (int&) error code
* @code
* int nError;
* bool Open("test.xls", nError);
* @endcode
* @return if sucess ture, otherwise false
* @see Close();
*/
bool Open(std::string strPath, int& nError);
1.1
define이나 변수 선언 #
#define 정의나 변수에 대한 것은 다음과 같이 작성할 수 있을 것이다.
/**
* temp file for parsing
*/
#define TEMP_FILE "TEMP_FILE"
/**
* file fd for temp file
*/
int gnFd;
1.2
struct나 enum #
struct나 enum은 다음과 같이 작성할 수 있을 것이다.
/**
* test enum
*/
enum TestEnum
{
ONE = 1, /**< one */
TWO, /**< two */
};
/**
* test struct
*/
struct TestStruct
{
int nA; /**< int value */
bool bB; /**< bool value */
};
2
그룹핑 (Grouping) #
함수나 클래스들을 묶을 수 있는 그룹핑 (Grouping)에 대해서 설명한다.
addtogroup
을 쓸 수도 있겠지만 한 파일에서만 쓸 수 있는 것 같아서 여러 파일에 걸쳐서 그룹핑을 할 수 있는
ingroup 을 사용하는 것에 대해서 설명한다. 이 설명은 Dogyxen 홈페이지의
여기를 참조했다.
- 그룹의 선언: defgroup
- 그룹명과 그룹에 대한 설명을 선언할 수 있다.
- 여러 파일일 경우 한 파일에만 선언해주면 된다.
- 그룹에 포함: ingroup
- 클래스나 함수를 그룹에 포함 시킬 수 있다.
- 클래스를 그룹에 포함시켰으면 클래스 멤버 함수는 그룹에 대해서는 ingroup을 사용할 필요는 없다.
예제는 다음과 같다.
/** @defgroup group1 The First Group
* group1이라는 그룹을 선언했다.
*/
/**
* @brief class C1 은 group1에 속하게 된다.
* @ingroup group1
*/
class C1 {};
/**
* @brief fucn1은 group1에 속하게 된다.
* @ingroup group1
*/
void func1();
//
3
그래프와 다이어그램 그리기 #
다음과 같이 Doxygen을 이용해서 그래프나 여러 형태의 다이어그램을 그릴 수 있다.


이 것에 대한 설명은
이
페이지를 참고했다. 방법은 다음과 같다.
3.1
Graphviz 설치 #
Doxygen은 Graphviz의 dot 프로그램을 이용해서 그림을 그린다. 그래서 먼저
http://www.graphviz.org/에 접속해서 좌측의 “다운로드”를
클릭하고 다음 페이지 하단의 “Agree”를 클릭해서 리눅스나 윈도우 버전의 설치 프로그램을 받으면 된다.
두
형태의 파일이 있는데 graphvizXXX.static.exe와 같은 형태를 받아서 설치하는 것이 좋다.
- “Expert” , “Dot” 탭에서 그리고자 하는 그래프와 다이어그램을 설정한다.
- “DOT_PATH”에 설치한 Graphviz의 bin 폴더를 지정해준다.
4
Doxygen 설치 #
Doxygen을 사용하기 위한 Doxygen 설치에 대해서 설명하겠다.
![[http]](/moniwiki/imgs/http.png)
Doxygen 사이트에 접속해서 binary를 다운 받는다.
![[http]](/moniwiki/imgs/http.png)
Doxygen download page에서 중간 정도에 있는 Doxygen source and binary releases에서 최신
버전의 binary를 다운 받는다 (※ 이 글을 쓸 때는 1.5.2였다).
5
DoxyWizard로
간단하게 Doxygen 만들어 보기 #
DoxyWizard로
간단하게 Doxygen 문서 (html,
LaTex, xml, chm, etc)를 만들 수 있다. Doxygen은
“Config”를 가지고 작업을 수행한다. 말 그대로 설정 파일이며 이 것은
DoxyWizard의 UI에서 수정할 수도 있고 직접 파일을 수정할
수도 있다. 아무튼 Doxygen 문서를 만들 때 Doxygen 프로그램은 “Config” 파일을 필요로 하고 아래 설명은 Config 파일을
DoxyWizrd를 이용해서
생성/설정하고 Config 파일을 이용해서 Doxygen 문서를 만드는 것에 대해서 간단히 설명한다.
DoxyWizard를
수행시키면 아래와 그림과 같은 다이얼로그가 보이고, Doxygen을 만드는 4단계 별로 구성되어 있다.
5.1
Step1. Configuration Doxygen #
Doxygen을 만들 때 wizard로 쉽게 만들 것인지 expert로 좀 더 다양한 설정을 할 것인지 아니면 기존에 만들어 둔 설정을
로딩할 것인지를 결정한다.
- Wizard:처음 만들 때 간단하게 Project 명과 버전, 소스 위치와 출력물이 나올 경로만 선택해주면 된다.
- 물론 Output이나 Diagrams에서 기타 설정을 할 수 있다.
- Wizard를 클릭하면 아래와 같은 다이얼로그가 나오고 위에서 거론된 정보들을 입력하고 “OK” 버튼을 클릭하면 된다.
Expert는 Wizard에서 가능한 설정을 포함해서 좀 더 다양한 설정을 할 수 있다. 아래에 소개되는 chm 파일도 Expert에서
설정할 수 있다.
기존에 만들어 둔 Config를 로딩하는 기능이다.
5.2
Step2. Save the configuration file #
위에서 설정한 configuration 파일을 저장한다. Step 1의 “Load…”에서 나중에 읽어 드릴 수 있고 또한 이 파일을
이용해서 Doxygen 문서를 만들어 낸다.
5.3
Step3. Specify the directory from which to run doxygen #
Working directory를 설정한다. working directory는 doxygen이 실행될 위치로 소스 패스를 설정하면 될
것이다.
5.4
Step4. Run doxygen #
모든 설정이 완료 되었으면 “Start” 버튼이 활성화 될 것이고 버튼을 클릭하면 로그 창에서 분주하게 doxygen 문서를 생성하는
것이 보일 것이고 완료가 되면 지정한 출력 폴더에 doxygen 문서들이 보일 것이다.
6
chm (도움말) 파일 만들기 #
Doxygen을 html로 만드는 것도 유용하지만 아래 그림과 같이 chm 파일로 Doxygen을 만드는 것도 배포하기도 편해서 필요할
것이다.
Doxygen에서 chm 파일을 만드는 것에 대해서 간단히 설명하면 아래와 같다.
6.2
DoxyWizard
설정 #
- DoxyWizard 실행
- 기존 설정한 config 파일이 있으면 “Load”를 클릭해서 로딩한다.
- “Expert…” 버튼을 클릭한다.
- “HTML” 탭에서 중간 정도의 “GENERATE_HTMLHELP”를 선택한다.
- 바로 아래의 CHM_FIL에 chm 파일 이름을 기재한다.
※ 별도 경로를 기재하지 않으면 html이 생성되는 위치에 생성된다.
- “HHC_LOCATION”에 위에서 설치 확인한 MS HTML Help의 hhc.exe의 위치를 설정하낟.
- 확인을 누르고 doxygen을 생성하면 html 경로에 chm 파일이 생성될 것이다.
7.1
Config 파일 수정 #
DoxyWiard에서 할
수 있는 설정들은 config 파일을 열어서 직접 각 option들을 수정함으로써 가능하다.
7.2
Tree 보여주기 #
HTML에서 프레임이 나누어져서 왼쪽에 탐색을 할 수 있는 트리를 보여주기 위해서는 다음과 같이 설정해주면 된다.
- DoxyWizard의
“HTML” 탭에서 하단의 “GENERATE_TREEVIEW”를 체크해주면 된다.
==== 파일명 축약해서
보여주기 ====
- 생성된 Doxygen 문서의 파일 트리에서 파일 명이 전체 경로로 나와있으면 보기 불편하기 아래 설정을 통해서 파일명만 보여줄 수 있다.
- “Expert”, “Project” 탭, “FULL_PATH_NAMES” 체크 해제
7.3
class의 protected나 private 보여주기 #
- 아무런 설정 없이 doxygen 문서를 만들면 private이나 protected 함수는 doxygen에 나타나지 않는다. 이러한 것들을
모두 doxygen 문서에 나타내고 싶은 경우
- DoxyWizard의
“Expert”의 “Build” 탭에서 EXTRACT_로 시작하는 부분을 체크해주면 된다. “EXTRACT_PRIVATE”을 클릭하면
private 함수들이 보여지는 식이다.
7.4
한글 보여주기 문제 #
- 1.5.2에서는 한글이 조금 문제였지만 (물론 INPUT_ENCODING을 CP949로 하면 된다) 1.5.4에서는 EUC-KR 등으로 변경해도 한글이 잘
나온다.
- 입력되는 소스 코드의 한글 주석을 위한 인코딩 방식은 “DoxyWizard”, “Expert”,”INPUT”의
“INPUT_ENCODING”에 아래 방식들을 선택하면 된다.
Korean
EUC-KR, CP949, ISO-2022-KR, JOHAB
- 생성된 페이지에 대한 한글 처리는 “DoxyWizard”, “Expert”, “Project”의
“DOXYFILE_ENCODING”에서 인코딩 방식을 변경한다.
- 인코딩 관련 설명은 아래 사이트에서 볼 수 있다.
- doxygen은 libiconv라는 라이브러리를 이용해서 언어처리를 하고 있고 libiconv의 인코딩 방식은 아래 사이트에 열거되어
있다.
Introduction to
libiconv