CommonLib 9.0

CommonLib Library, version 9.0, December 2009

CommonLib to uniwersalna biblioteka dla C++ zawierająca różnorodne elementy. Powstała przy okazji pisania silnika graficznego i różnych innych moich projektów. Obecna wersja jest pisana od wakacji 2006.

Właściwie od dziecka, odkąd tylko zacząłem programować (wtedy to był jeszcze Turbo Pascal pod DOS) zawsze rozwijałem jakąś swoją bibliotekę modułów bazowych, z którymi potem nigdy się nie rozstawałem pisząc swoje projekty. Teraz uważam, że nadal jest to potrzebne - szczególnie w C++, którego biblioteka standardowa - w przeciwieństwie do nowoczesnych języków i środowisk programowania takich jak Delphi, C# czy Java - jest bardzo uboga, a to co zawiera pozostawia wiele do życzenia.

Cechy i założenia

Jak użyć

Biblioteka ma postać plików z kodem C++ - CPP i HPP. Możesz z tym kodem zrobić co chcesz. Najprościej jest po prostu skopiować te pliki i dodać do swojego projektu.

Poniżej opisana jest jedna z możliwości - przygotowanie kodu jako biblioteki LIB i jej użycie w projekcie w Visual C++ 2005. Niestety nie jest to tak banalne jak rozpakować i od razu zacząć używać. To nie moja wina - takie są uroki języka C++...

Aby przygotować bibliotekę LIB:

  1. Utwórz projekt Visual C++ lub otwórz istniejący, który znajdziesz w pliku Common.sln.
  2. Wejdź do opcji projektu i zmień:
    1. Configuration Properties / General / Character Set: zależnie czy chcesz używać Unicode, ustaw na "Not Set" lub "Use Unicode Character Set" (w obydwu konfiguracjach - Debug i Release).
    2. Configuration Properties / C/C++ / Code Generation / Runtime Library: zależnie jak będziesz kompilował kod swoich programów korzystających z CommonLib: jeśli chcesz aby nie musiały używać dodatkowych plików DLL z biblioteką standardową C (których część użytkowników nie ma), przestaw na "Multithreaded Debug" (konfiguracja Debug) i "Multithreaded" (konfiguracja Release). Jeśli wolisz otrzymywać mniejsze pliki EXE, wybierze "Multithreaded Debug DLL" (konfiguracja Debug) i "Multithreaded DLL" (konfiguracja Release).
    3. Configuration Properties / C/C++ / Preprocessor / Preprocessor Definitions: W obydwu konfiguracjach (w każdej osobno) dopisz wybrane makra odpowiednio do bibliotek, których będziesz używał w swoim kodzie: USE_DIRECTX, USE_SDL, USE_OPENGL, USE_FMOD, USE_WINSOCK, USE_DEVIL, USE_AVI_FILE
    4. Jeśli nie masz zainstalowanej biblioteki zlib, nie chcesz jej używać albo w ogóle nie wiesz co to jest, usuń z projektu pliki ZlibUtils.cpp i ZlibUtils.hpp.
  3. Skompiluj bibliotekę w obydwu konfiguracjach - Debug i Release.
  4. Załóz na swoim dysku jakiś katalog, gdzie umieścisz skompilowaną bibliotekę jako gotową do używania w projektach. Utwórz w nim podkatalog include i skopiuj do niego pliki HPP. Utwórz katalog lib i skopiuj do niego pliki Common.lib (który powstał w podkatalogu Release) i Common_d.lib (który powstał w katalogu Debug).
  5. Skonfiguruj ścieżki do katalogów w Visual C++. W tym celu wybierze polecenie z menu Tools / Options. Po lewej zaznacz Projects and Solutions / VC++ Directories. Do "Include files" dopisz ścieżkę do podkatalogu includes. Do "Library files" dopisz ścieżkę do podkatalogu lib.

Aby skorzystać z tak skompilowanej biblioteki w swoim projekcie:

  1. Utwórz lub otwórz istniejący projekt programu w Visual C++.
  2. Dołącz wybane nagłówki biblioeki w postaci takiej jak np. include <Common/Base.hpp>. Jeśli używasz jakichkolwiek nagłówków CommonLib, musisz najpierw włączyć nagłówek Base.hpp.
  3. Wejdź do opcji projektu i zmień:
    1. Configuration Properties / General / Character Set: Tak jak wyżej.
    2. Configuration Properties / C/C++ / Code Generation / Runtime Library: Tak jak wyżej.
    3. Configuration Properties / C/C++ / Preprocessor / Preprocessor Definitions: Tak jak wyżej.
    4. Configuration Properties / Linker / Input / Additional Dependencies: Dopisz potrzebne biblioteki LIB. Musisz dopisać w konfiguracji Debug plik CommonLib_d.lib, a w konfiguracji Release plik CommonLib.lib. Dodatkowo zależnie od innych użytych bibliotek, listę plików należy uzupełnić o:
      1. Jeśli używasz USE_DIRECTX: d3d9.lib d3dx9.lib dxerr9.lib
      2. Jeśli używasz modułu ZlibUtils: zlibd.lib (Debug), zlib.lib (Release)

Składniki i możliwości

Base Module

Module with lots of different, general functionality.

Documentation: Module_Base
Module elements: Base Module
Header: Base.hpp

BstrString Module

Object-oriented wrapper for Unicode string of type BSTR.

Documentation: Module_BstrString
Module elements: BstrString Module
Header: BstrString.hpp

DateTime Module

Support for date and time.

Documentation: Module_DateTime
Module elements: DateTime Module
Header: DateTime.hpp

Error Module

Klasy wyjątków do obsługi błędów

Documentation: Module_Error
Module elements: Error Module
Header: Error.hpp

Files Module

Code for dealing with files and file system.

Documentation: Module_Files
Module elements: Files Module
Header: Files.hpp

FreeList Module

Very fast memory allocator.

Documentation: Module_FreeList
Module elements: FreeList Module
Header: FreeList.hpp

Szablony klas common::FreeList oraz common::DynamicFreeList. Obiekty tych klas to napisane we własnym zakresie alokatory przeznaczone do alokowania dużych ilości zmiennych jednego wybranego typu, które działają znacząco szybciej niż standardowe operatory new i delete.

Logger Module

A code for logging messages.

Documentation: Module_Logger
Module elements: Logger Module
Header: Logger.hpp

Math Module

Mathematical structures and functions, especially for 2D and 3D geometry.

Documentation: Module_Math
Module elements: Math Module
Header: Math.hpp

ObjList Module

Macros for creating doubly-linked list of objects.

Documentation: Module_ObjList
Module elements: ObjList Module
Header: ObjList.hpp

Profiler Module

Classes for measuring time and performance.

Documentation: Module_Profiler
Module elements: Profile module
Header: Profiler.hpp

Stream Module

Stream class hierarchy.

Documentation: Module_Stream
Module elements: Stream Module
Header: Stream.hpp

Threads Module

Portable library for multithreading and synchronization.

Documentation: Module_Threads
Module elements: Threads Module
Header: Threads.hpp

Tokenizer Module

Parser and writer for a syntax based on tokens, simiar to C/C++.

Documentation: Module_Tokenizer
Module elements: Tokenizer Module
Header: Tokenizer.hpp

TokDoc Module

Persistent DOM model for a format based on Tokenizer.

Documentation: Module_TokDoc
Module elements: TokDoc Module
Header: TokDoc.hpp

ZlibUtils Module

A convenient wrapper for zlib compression library.

Documentation: Module_ZlibUtils
Module elements: ZlibUtils Module
Header: ZlibUtils.hpp

D3DX Integration

If you use DirectX 9.0c with D3DX, you can integrate CommonLib with it to make math data structures compatible. Without D3DX integration, Math module defines its own structures: VEC2, VEC3, VEC4, PLANE, MATRIX, QUATERNION. Their interface is very similar to structures from D3DX and their data layout is identical.

To integrate CommonLib with D3DX, define macro USE_DIRECTX for the whole project. When defined, it makes Math to define types mentioned above as typedefs to types D3DXVECTOR2, D3DXVECTOR3, D3DXVECTOR3, D3DXPLANE, D3DXMATRIX, D3DXQUATERNION from D3DX instead of defining its own structures. It makes all math functions compatible with DirectX interface. Thanks to that you can mix DirectX type names with CommonLib type names freely, as well as use CommonLib math functions next to D3DX functions. For example, these two code samples do exactly the same thing:

D3DXVECTOR3 dxVec = D3DXVECTOR3(1.f, 2.f, 3.f);
common::Normalize(&dxVec);

common::VEC3 commonLibVec = common::VEC3(1.f, 2.f, 3.f);
D3DXVec3Normalize(&commonLibVec, &commonLibVec);

Obsługa Unicode

Od wersji 8.0 biblioteka posiada w systemie Windows możliwość pracy ze znakami i łańcuchami Unicode. Aby przełączyć CommonLib w tryb pracy z Unicode, należy podjąć te same kroki, co podczas przełączania do tego trybu WinAPI i DirectX. Trzeba w tym celu zdefiniować dla całego projektu makra preprocesora UNICODE i _UNICODE. W przypadki Visual C++ można przestawić w opcjach projektu, na zakładce Configuration Properties / General, opcję Character Set na Use Unicode Character Set - wówczas to makro zostanie dodane automatycznie.

Przy starannym stosowaniu się do poniższych zaleceń można pisać kod programu korzystający z WinAPI, DirectX i CommonLib tak, aby kompilował się i działał zarówno ze znakami Unicode, jak i zwykłymi ANSI, bez jakichkolwiek zmian w kodzie (wystarczy zmiana opisanego wyżej ustawienia).

Moduł definiuje typ znakowy common::tchar jako alias do char lub wchar_t oraz typ łańcuchowy common::tstring jako alias do std::string lub std::wstring, zależnie od ustawienia. Prawie wszystkie klasy i funkcje CommonLib korzystają z tych typów, tak że automatycznie przełączają się na używanie znaków i łańcuchów Unicode zależnie od tego ustawienia.

Łańcuch znaków ANSI zapisuje się w kodzie C++, jak wiadomo, w taki sposób: "ABC". Łańcuch znaków Unicode zapisuje się tak: L"ABC". Moduł Base definiuje makro, którym należy obejmować wszystkie łańcuchy w kodzie, jeśli chcemy, aby zostały zamienione na odpowiednią postać (ANSI lub Unicode) zależnie od ustawienia. Przykład: _T("ABC").

Jeśli piszemy kod, który ma działać zarówno ze znakami ANSI jak i Unicode, jako makro oznaczające nazwę bieżącego pliku źródłowego (podawane do konstruktora klas wyjątków modułu Error) używać należy zdefiniowanego w module Base makra __TFILE__. Podobnie, makro przechowujące sygnatuję bieżącej funkcji to __TFUNCSIG__.

Do konwersji między standardami kodowania znaków użyj funkcji common::ConvertUnicodeToChars i common::ConvertCharsToUnicode. Działają one tylko w Windows. Są niezależne od ustawienia _UNICODE. Pozwalają zamieniać łańćuchy między kodowaniem UTF-16 (Unicode), UTF-8 i ANSI (np. Windows-1250 w przypadku języka polskiego).

Jeśli piszesz kod, który ma się kompilować bez zmian zarówno w ANSI jak i Unicode, przydatne będą funkcje konwertujące łańćuchy między kodowaniem ASNI (typ string) lub Unicode (typ wstring), a tym używanym zależnie od ustawienia (typ common::tstring). Te funkcje to: common::TstringToString, common::StringToTstring, common::TstringToWstring, common::WstringToTstring. Jak można się domyślić, połowa z nich (która, to zależy od ustawienia) nic nie robi, tylko zwraca podany łańcuch.

Do zapisywania i odczytywania plików tekstowych w różnym kodowaniu służą funkcje modułu Files: common::SaveUnicodeToFile, common::SaveUnicodeToStream, common::LoadUnicodeFromFile, common::LoadUnicodeFromStream. W razie potrzeby automatycznie konwertują kodowanie znaków. Obsługują kodowanie ANSI, UTF-16 LE i UTF-8. Funkcje zapisujące mogą dołączać nagłówek BOM. Funkcje odczytujące, na podstawie nagłówka i analizy treści, mogą automatycznie rozpoznać kodowanie.

Mini FAQ

Skąd taka nazwa?

W moim głównym kodzie, z którego biblioteka się wywodzi, mam w Visual C++ w Solution szereg projektów. Jednym z nich jest silnik graficzny, innym pomocnicze narzędzie konsolowe czy program testujący. Kod wspólny dla wszystkich projektów zgromadziłem w katalogu, który nazwałem Common i tak już zostało.

Skąd taka wersja?

Faktycznie nie było CommonLib 4 czy 5, a wersja 6.1 była tak różna od 6.0, że powinna się nazywać 7.0. Jednak chciałem zrównać numerację biblioteki z numeracją mojego głównego projektu - silnika graficznego, na potrzeby którego napisałem tą bibliotekę.

Nowe wydanie - CommonLib 8.0 - nie oznacza że zacząłem pisać od nowa swój silnik graficzny. Oznacza raczej, że biblioteka przeszła wielkie zmiany po tym, jak silnik w wersji 7 został uznany za skończony.

Co nowego?

Version 9.0 (December 2009)

I've used CommonLib with all my C++ home projects in recent year, so many new ideas about changes and new features came to my mind. This version is just the implementation of some of them (these simpler and smaller ones :) I have also much more experience in programming because of my work in game development industry and then digital television industry.

This is a big release. Some completely new modules appeared. WARNING 1: This version is not fully compatible with the previous one, as some of elements have been deleted or significantly changed. WARNING 2: This version is tested only with Microsoft Visual C++ 2008 compiler and does not ensure compatiblity with Linux!

Wersja 8.1 (10 listopada 2008)

Przez ostatnie miesiące biblioteka była rozwijana częściowo samodzielnie, a częściowo przy okazji różnych programów. Największym zmianom uległ moduł matematyczny, do którego dodane zostało wiele nowych funkcji do kolizji, napisanych głównie dzięki lekturze książki "Real-Time Collision Detection", Christer Ericson. Wersja 8.1 nie jest w pełni kompletna (wiele nowych możliwości jest w planach), ale stanowi zebranie tego, co zostało dotychczas dodane. Poprawieniu lub przepisaniu na bardziej optymalną wersję uległo wiele procedur. Poniższa lista zawiera tylko spis zmian w zewnętrznym interfejsie biblioteki.

Wersja 8.0 (29 marca 2008)

Biblioteka przeszła wielkie zmiany. Logicznie większość kodu jest nadal kompatybilna wstecz, ale tekstowo zmiany są tak duże, że praktycznie nie ma sensu robić Diff. Ogólne, duże nowości:

Inne zmiany:

Wersja 7.0 (3 listopada 2007)

Biblioteka była przez ostatnie miesiące uzupełniana i poprawiana na bieżąco wraz z rozwojem silnika graficznego 3D, na potrzeby którego powstała.

Wersja 6.1 (29 czerwca 2007)

Od wersji 6.0 biblioteka zmieniła się właściwie nie do poznania. Dlatego nie ma sensu wypisywać zmian. Szczególnie, że pewnie nikt z niej wcześniej nie korzystał :P

Licencja

Biblioteka dostępna jest na licencji GNU LGPL, co znaczy m.in., że masz dostęp do jej kodu źródłowego oraz że możesz używać jej za darmo w dowolnych swoich programach, także zamkniętych.

Autor

Adam Sawicki
E-mail: sawickiap@poczta.onet.pl
Homepage: http://regedit.gamedev.pl


Generated on Wed Dec 16 20:44:52 2009 for CommonLib by  doxygen 1.6.1