Engine (1.) - Logování
Rád pozoruji programovací styl ostatních programátorů ale všiml jsem si, že spousta lidí vůbec netestuje chybné inicializace důležitých modulů a v případě že program spadne netuší, v čem může být chyba. Přitom důkladné testování by měla být úplná samozřejmost. Přitom řešení je jednoduché vytvořením třídy pro ukládání informací do logovacího souboru, kterou dnes popíši.
Všechny zdrojáky zde uvedené budou vycházet z mého vlastního enginu tak se nedivte že neposkytuji nějaký funkční program, ale že vždy popíši pouze určitý odladěný modul. Tak jdeme na to. Rozhrání modulu je v hlavičkovém souboru CLog.h jehož celý výpis je zde:
//-----------------------------------------------------------
// MODUL: CLog.h
// PROJECT: 3D engine
// AUTHORS: Roman Schulz, rschulz@centrum.cz
//-----------------------------------------------------------
#ifndef _CLog_H_
#define _CLog_H_
class CLog
{
public:
CLog() {};
~CLog() {};
void Init(char *FileName);
void NewLine();
void NewLine(char *Text, ...);
void AddLast(char *Text);
void HexDumpData(char *data, int size);
protected:
char m_FileName[127];
};
#endif
V podstatě se jedná pouze o třídu, jejíž nejdůležitější metody jsou NewLine a AddLast. Nejdříve je však potřeba třídu inicializovat zadáním jména výstupního souboru. O to se stará metoda Init, která vytvoří nový soubor nebo vymaže obsah původního souboru pro logování údajů. Samozřejmě nesmí chybět načtení hlavičkových souborů s používanými funkcemi:
//----------------------------------------------------------- // MODUL: CLog.cpp // PROJECT: 3D engine // AUTHORS: Roman Schulz, rschulz@centrum.cz // DESCRIPTION: //----------------------------------------------------------- #include "CLog.h" #include "CTimer.h" #include#include #include #include //----------------------------------------------------------- // Name: Init() // Desc: Fce slouzi k ulozeni jmena souboru a jeho otevreni //----------------------------------------------------------- void CLog::Init(char *FileName) { FILE *LOGFile; // Ulozi jmeno logovaciho souboru strcpy(m_FileName, FileName); // Vymaze obsah souboru LOGFile = fopen(m_FileName, "wt"); // Zavre soubor fclose (LOGFile); }
Myslím, že překopírovat tohle zvládne každý, kdo už nějaký ten prográmek v céčku vytvářel. Teď přejdu k něčemu jen o trochu složitějšímu. Jedná se o metody s velmi podobnými funkcemi. Jedná se o metody NewLine a AddLast. Nejjednoduší s těchto 3 metod je NewLine() která do logovacího souboru uloží prázdný řádek, který slouží ke zpřehlednění uložených údajů. Druhá podobná metoda je NewLine(char *Test, ...), která má parametry úplně stejné jako funkce printf() a která slouží k formátování textu a jeho uložení do souboru. Poslední z těchto funkcí je AddLast(char *Text) která slouží k dokončení zprávy uložené v logovacím souboru, například text "OK", "Failed" nebo podobně. Zde je výpis těchto funkcí:
//-----------------------------------------------------------
// Name: NewLine()
// Desc: Sem budeme zapisovat vsechny zpravy
//-----------------------------------------------------------
void CLog::NewLine(char *Text, ...)
{
FILE *LOGFile;
char Line[1024];
va_list ArgP;
// Konvertuje parametry do retezce
va_start(ArgP, Text);
vsprintf(Line, Text, ArgP);
va_end(ArgP);
// Pokusi se otevrit zadany soubor
if ((LOGFile = fopen(m_FileName, "a+")) == NULL)
{
return;
}
// Ukonci predchozi radek
putc('\n', LOGFile);
// Zapis radek do souboru
fprintf(LOGFile, Line);
// Uzavreni souboru
fclose(LOGFile);
}
//-----------------------------------------------------------
// Name: NewLine()
// Desc: Pretizena funkce NewLine pro vlozeni prazdneho radku
//-----------------------------------------------------------
void CLog::NewLine()
{
FILE *LOGFile;
// Pokusi se otevrit zadany soubor
if ((LOGFile = fopen(m_FileName, "a+")) == NULL)
{
return;
}
// Ukonci radek
putc('\n', LOGFile);
// Uzavreni souboru
fclose(LOGFile);
}
//-----------------------------------------------------------
// Name: AddLast()
// Desc: Touto funkci dokoncime informaci na radku: ...OK
//-----------------------------------------------------------
void CLog::AddLast(char *Text)
{
FILE *LOGFile;
// Pokusi se otevrit zadany soubor
if ((LOGFile = fopen(m_FileName, "a+")) == NULL)
{
return;
}
// Vloz text na konec posledni radky
fprintf(LOGFile, Text);
// Uzavreni souboru
fclose(LOGFile);
}
Poslední metodou, kterou dnes zmíním, je HexDumpData. Tato metoda slouží k haxadecimálmímu výpisu dat do souboru. Určitě se bude časem hodit každému programátorovi, její parametr je ukazatel do paměti a velikost dat, metoda do logovacího souboru uloží přehlednou tabulku s výpisem dat. Podrobně zde metodu rozebírat nebudu, ale každý kdo o to bude mít zájem si ji může podrobně prozkoumat sám. Jsme přece programátoři a nesmíme se toho bát:-)
//-----------------------------------------------------------
// Name: HexDumpData()
// Desc: Vypise na obrazovku data v HEXa tvaru
// From: www.designcurve.net
//-----------------------------------------------------------
void CLog::HexDumpData(char *data, int size)
{
int i, bytes_left, bytes = 0;
unsigned char dump[15];
FILE *LOGFile;
// Pokusi se otevrit zadany soubor
if ((LOGFile = fopen(m_FileName, "a+")) == NULL)
{
return;
}
if (data && size)
{
fprintf(LOGFile, "\n\n");
fprintf(LOGFile, "-----------------------------------------------------------------------------\n");
fprintf(LOGFile, "|Address | HEX | ASCII |\n");
fprintf(LOGFile, "-----------------------------------------------------------------------------\n");
while (bytes < size)
{
memset(dump, 0, sizeof(dump));
bytes_left = size - bytes;
if (bytes_left >= 16)
{
memcpy(&dump, &data[bytes], 16);
fprintf(LOGFile, "|%8X| %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X |",
bytes & 0xFFFFFFF0, dump[0], dump[1], dump[2], dump[3], dump[4], dump[5], dump[6], dump[7],
dump[8], dump[9], dump[10], dump[11], dump[12], dump[13], dump[14], dump[15]);
fprintf(LOGFile, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c|\n",
isprint(dump[0]) ? dump[0] : '.', isprint(dump[1]) ? dump[1] : '.', isprint(dump[2]) ? dump[2] : '.',
isprint(dump[3]) ? dump[3] : '.', isprint(dump[4]) ? dump[4] : '.', isprint(dump[5]) ? dump[5] : '.',
isprint(dump[6]) ? dump[6] : '.', isprint(dump[7]) ? dump[7] : '.', isprint(dump[8]) ? dump[8] : '.',
isprint(dump[9]) ? dump[9] : '.', isprint(dump[10]) ? dump[10] : '.', isprint(dump[11]) ? dump[11] : '.',
isprint(dump[12]) ? dump[12] : '.', isprint(dump[13]) ? dump[13] : '.', isprint(dump[14]) ? dump[14] : '.',
isprint(dump[15]) ? dump[15] : '.');
bytes += 16;
}
else if (bytes_left > 0)
{
memcpy(&dump, &data[bytes], bytes_left);
bytes += bytes_left;
fprintf(LOGFile, "|%8X| ", bytes & 0xFFFFFFF0);
/* Hex side */
for (i = 0; i < bytes_left; i++)
fprintf(LOGFile, "%2X ", dump[i]);
/* Pad Hex side with spaces */
for (/* */; i < 16; i++)
fprintf(LOGFile, " ");
/* Separator */
fprintf(LOGFile, "|");
/* Ascii side */
for (i = 0; i < bytes_left; i++)
fprintf(LOGFile, "%c", isprint(dump[i]) ? dump[i]: '.');
/* Pad ascii side with spaces */
for (/* */; i < 16; i++)
fprintf(LOGFile, " ");
/* End of line */
fprintf(LOGFile, "|\n");
}
}
fprintf(LOGFile, "-----------------------------------------------------------------------------\n\n");
bytes++;
}
// Uzavreni souboru
fclose(LOGFile);
}
Na závěr ještě uvedu příklad použití tohoto modulu:
#include "headers/CLog.h"
CLog Log;
int main()
{
Log.Init("Log/Log.txt");
....
// Vyhleda format odpovidajici pozadavkum
Log.NewLine("Finding Suitable Pixel Format...");
if (m_PixelFormat = ChoosePixelFormat(g_hDC, &pfd))
{
Log.AddLast("OK");
}
else
{
Log.AddLast("Failed");
return false;
}
// Nastavi vybrany format
Log.NewLine("Setting Pixel Format...");
if (SetPixelFormat(g_hDC, m_PixelFormat, &pfd))
{
Log.AddLast("OK");
}
else
{
Log.AddLast("Failed");
return false;
}
....
}
A příklad logovacího souboru, který vznikl v tomto modulu:
--------------------------------------------------
Project: 3D Graphic Engine
Author: Roman Schulz, Czech Republic
Contact: rschulz@centrum.cz
--------------------------------------------------
Processor:
Frequency: 0 MHz
Vendor: GenuineIntel
Type: Original OEM
Family: Intel Pentium Pro (80686)
Brand ID: Intel Celeron M (0.09 µm)
Model: Intel Celeron M
Serial: No Processor Serial Number
Processor Features:
AMD 64bit Architecture: NO
Intel 64bit Architecture (IA64): NO
Thermal Monitor: YES
Thermal Monitor And Clock Control: YES
Floating Point Unit (FPU): YES
Fast Streaming SIMDExtensions Save/Restore:YES
Hyper Threading: NO
Multimedia Extensions (MMX): YES
Extended Multimedia Extensions (MMX+): NO
Streaming SIMD Extensions (SSE): YES
Streaming SIMD2 Extensions (SSE2): YES
3DNow! Instructions: NO
Enhanced 3DNow! Instructions: NO
Initialising Window:
Registering Window Class...OK
Creating Window...OK
Getting a Device Context...OK
Setting Up Display Mode 1024x768x16...OK
Initialising OpenGL:
Finding Suitable Pixel Format...OK
Setting Pixel Format...OK
Creating OpenGL Rendering Context...OK
Activating OpenGL Rendering Context...OK
Initialising OpenGL Extensions:
Setting Up Multitexture Support...OK
Number Of Texture Units...4
Settings Up Texture Compression Support...OK
Checking Hardware Acceleration...Supported (ICD)
OpenGL Features:
Manufacturer...Intel
Renderer...Intel Montara-GM
Version...1.3.0 - Build 4.14.10.3712
Buffer Mode...Double Buffering
Color Buffer...16 Bits (5650)
Depth Buffer...16 Bits
Stencil Buffer...0 Bits
Accumulation Buffer...64 Bits (16161616)
Num Of Auxiliary Buffers...0
Maximum Texture Size...2048x2048 Pixels
Maximum Num Of Lights...16
Supported Extensions:
GL_ARB_multitexture
GL_ARB_texture_border_clamp
GL_ARB_texture_compression
GL_ARB_texture_cube_map
GL_ARB_texture_env_add
GL_ARB_texture_env_combine
GL_ARB_texture_env_dot3
GL_ARB_texture_env_crossbar
GL_ARB_transpose_matrix
GL_EXT_abgr
GL_EXT_bgra
GL_EXT_blend_color
GL_EXT_blend_func_separate
GL_EXT_blend_minmax
GL_EXT_blend_subtract
GL_EXT_clip_volume_hint
GL_EXT_compiled_vertex_array
GL_EXT_cull_vertex
GL_EXT_fog_coord
GL_EXT_packed_pixels
GL_EXT_packed_pixels_12
GL_EXT_rescale_normal
GL_EXT_secondary_color
GL_EXT_separate_specular_color
GL_EXT_stencil_wrap
GL_EXT_texture_compression_s3tc
GL_EXT_texture_env_add
GL_EXT_texture_env_combine
GL_EXT_texture_filter_anisotropic
GL_3DFX_texture_compression_FXT1
GL_IBM_texture_mirrored_repeat
GL_NV_texgen_reflection
GL_WIN_swap_hint
Initializing Direct Input:
Creating Direct Input Object...OK
Creating Keyboard Device...OK
Creating Mouse Device...OK
Setting Up Keyboard Cooperative Level...OK
Setting Up Mouse Cooperative Level...OK
Setting Up Keyboard Data Format...OK
Setting Up Mouse Data Format...OK
Acquiring Keyboard Device...OK
Acquiring Mouse Device...OK
Initialising FMOD Sound System:
Checking DLL Version...OK
Setting Output Type...OK
Setting Up Sound Driver...OK
Setting Up Quality MMX Mixer...OK
Initializing FMOD Sound System...OK
FMOD Sound System Features:
Selected Output Type: Direct Sound
Selected Mixer Name: Interpolating Volume Ramping PPro+ MMX Mixer
Selected Driver: Primární ovladač zvuku
Checking 3D Sound Support...Failed
Checking EAX2 Reverb Support...Failed
Checking EAX3 Reverb Support...Failed
Number Of Allocated Channels...106
Number Of Hardware 3D Channels...10
A to je vše. Když program někde spadne, ihned vím v čem je chyba a to je obrovská výhoda logovacího souboru. Věřím, že se najde alespoň někdo kdo ocení tento modul vlastně celý článek a v případě zájmu budu pokračovat dalšími částmi mého enginu. Těším se na vaše reakce pod článkem...
Vyšlo 18.01.2005, v blogu: 0 1 2 3 4 5 6 7 8
Děkuji, že jste se rozhodl(a) přečíst tento článek. Budu rád i za komentář. Pokud Vás tento článek zaujal a rádi byste jej doporučili ostatním, podpořte mně prosím tím, že věnujete minutku svého času a uděláte mi reklamu na linkuj.cz, vybrali.sme.sk či jagg.cz. Přeji příjemné čtení
Poslední články
- Fotografie přírody z víkendového odpoledne
- Jak jsem přešel na Linux
- CZ,cracky a cd keygen
- Tenisti v akci...
- První příspěvek v blogu
- Zobrazení terénu ve 3D grafice
- Engine (2.) - Timing
- Engine (1.) - Logování
- OpenGL (17.) - Light mapping - úvod
- OpenGL (16.) - Fading
- Herní grafické enginy (3.) - GLScene
- Herní grafické enginy (2.) - Pythian Project
- OpenGL (15.) - Ucelený částicový systém - pokračování
- OpenGL (14.) - Ucelený částicový systém
- OpenGL (13.) - Nastavení OpenGL v jazyce C/C++