|
IntroductionOverviewDlib is a cross-platform open source software library written in the C++ programming language. Its design is heavily influenced by ideas from design by contract and component-based software engineering. This means it is, first and foremost, a collection of independent software components, each accompanied by extensive documentation and thorough debugging modes. Generally speaking, there is no focus on any specific domain in the library. It contains a variety of software objects for dealing with networking, threads (message passing, futures, etc.), graphical interfaces, complex data structures, linear algebra, machine learning, XML and text parsing, numerical optimization, Bayesian networks, and numerous other tasks. The most persistent theme in the library is the ubiquitous application of contract programming. You can read about this on the how to contribute page for more information. However, from the point of view of a user of this library it basically means there exists complete and precise documentation for every function and class in the library as well as aggressive debugging modes that can be enabled. I always try to make sure everything is as portable as possible. All platform specific code is confined inside the API wrappers. Everything else is either layered on top of those wrappers or is written in pure ISO standard C++. Currently the library is known to work on OS X, MS Windows, Linux, Solaris, the BSDs, and HP-UX. It should work on any POSIX platform but I haven't had the opportunity to test it on any others (if you have access to other platforms and would like to help increase this list then let me know). The rest of this page explains everything you need to know to get started using the library. It explains where to find the documentation for each object/function and how to interpret what you find there. For help compiling with dlib check out the how to compile page. Or if you are having trouble finding where a particular object's documentation is located you may be able to find it by consulting the index. The library is also covered by the very liberal Boost Software License so feel free to use it however you like. Much of the organization and notation used in this library I learned from the Software Component Engineering course sequence at OSU. NotationFor the most part I try to document my code in a way that any C++ programmer would understand, but for the sake of brevity I use some of the following uncommon notation.
For example, you might see a line in this section that says "my_size == size()". This just means that the member variable my_size always contains the value returned by the size() function.
OrganizationThe library can be thought of as a collection of components. Each component always consists of at least two separate files, a specification file and an implementation file. The specification files are the ones that end with _abstract.h. Each of these specification files don't actually contain any code and they even have preprocessor directives that prevent any of their contents from being included. Their purpose is purely to document a component's interface in a file that isn't cluttered with implementation details the user shouldn't need to know about. The next important concept in dlib organization is multi-implementation components. That is, some components provide more than one implementation of what is defined in their specification. When you use these components you have to identify them with names like dlib::component::kernel_1a. Often these components will have just a debugging and non-debugging implementation. However, many components provide a large number of alternate implementations. For example, the entropy_encoder_model has 32 different implementations you can choose from.
Creating ObjectsTo create many of the objects in this library you need to choose which kernel implementation you would like and if you want the checking version or any extensions. To make this easy there are header files which define typedefs of all this stuff. For example, to create a queue of ints using queue kernel implementation 1 you would type dlib::queue<int>::kernel_1a my_queue;. Or to get the debugging/checking version you would type dlib::queue<int>::kernel_1a_c my_queue;. There can be a lot of different typedefs for each component. You can find a list of them in the section for the component in question. For the queue component they can be found here. None of the above applies to the single-implementation components, that is, anything that doesn't have an "implementations" section in its documentation. These tools are designed to have only one implementation and thus do not follow the above naming convention. For example, to create a logger object you would simply type dlib::logger mylog("name");. For the purposes of object creation the API components also appear to be single-implementation. That is, there is no need to specify which implementation you want since it is automatically determined by which platform you compile under. Note also that there are no explicit checking versions of these components. However, there are DLIB_ASSERT statements that perform checking and you can enable them by #defining DEBUG or ENABLE_ASSERTS. AssumptionsThere are some restrictions on the behavior of certain objects or functions. Rather than replicating these restrictions all over the place in my documentation they are listed here.
Thread SafetyIn the library there are three kinds of objects with regards to threading. There are objects that are completely thread safe. Then there are objects that are not thread safe but can be used if access to them is serialized using a mutex. Lastly, there are objects which share some kind of global resource or are reference counted. The last kind of object is extremely thread unfriendly and can only be used in a threaded program with great care. How do you know which components/objects are thread safe and which aren't? The rule is that if the specification for the component doesn't mention threading or thread safety then it is ok to use as long as you serialize access to it. If the component might have some global resources or be reference counted then the specifications will tell you this. And lastly if the component is thread safe then the specification will tell you this also. |