Static Library ExampleDownload the solution here Download here . In addition to executable files we will also deal with 'libraries' in this class. There are both 'dynamic' and 'static' libraries. Dynamic libraries can be loaded at run-time, which means:
In our class our experience with dynamic libraries will be limited to Maya plug-ins (Maya will load libraries that we create and execute our code). All other libraries that we create will be static. Static LibrariesStatic libraries are separate files whose executable code gets embedded into the executable at build time. Functionally there is no real reason to use them in the way we will in this class as opposed to just putting the source files in a single project. The reason that we will use static libraries so extensively in this class is for organization: It allows us to create separate projects to handle separate responsibilities. This means:
All of the above arguments could also be made in favor of using dynamic libraries instead and many games do exactly that. Creation
Now when you build this project it will create a LIB file instead of an EXE file. The rest of the required set-up is the same as the other projects in our class. UsingLook at EntryPoint.cpp in the Executable project. This consists of a standard main() function like you are used to, and the only thing that this main() does is call two trivial example functions. The first function comes from the Static Library project (declared in StaticLibrary.h and defined in StaticLibrary.cpp), and the second comes from Windows. Notice that the C/C++ code doesn't care that these functions are from external libraries! It is exactly the same as if StaticLibrary.h and StaticLibrary.cpp (or the Windows message box code) were part of the Executable project. A consequence of this is that if you don't set up a static library correctly you will not get compile errors (the solution will compile successfully) but instead you will get linker errors: Compiling just guarantees that the calls to the static library have correct syntax (as determined by the header file), and it is the 'linker' that actually tries to associate ('link') the calls to the static library with real compiled machine code. When this happens you will see 'unresolved external symbol' errors (LNK2019 (Links to an external site.)). When you see an 'unresolved external symbol' error DON'T PANIC! Remember what it means: Your code is calling some externally-defined function correctly, but the linker can't find that externally-defined function and you need to help locate it. This is how you get Visual Studio to successfully use a static library that your project needs to call a function from:
When you do this the following should happen:
Static Library ChainsThis example program is simple and only has a single executable and a single static library. In many cases, however, you will encounter a situation where you have a chain of static libraries: Executable A calls a function from Static Library B, and Static Library B calls a function from Static Library C. In this hypothetical situation, even though Executable A never calls a function from Static Library C directly it still needs to link to it! This is because static libraries don't link to other static libraries: All of the executable code only gets embedded in the executable. Technically, then, no static library depends on any other static library. Instead, an executable depends on all of the static libraries that have functions called by any static library that it uses directly. Even though this is technically true, it is not how we want to think of things as humans because it is confusing and error prone. Using Visual Studio's reference mechanism allows us to worry about the conceptual dependencies of each static library in isolation. If Static Library B in your solution calls a function from Static Library C you should add Static Library C to the list of Static Library B's references. By doing this Visual Studio will automatically set up the dependencies and link all of the necessary projects to the final executable, and you do not need to set Library C as a reference of Executable A. (Each reference has a properties page that controls this behavior, but it is ok to leave the default values.) In summary: If a project X calls any functions from project Y then project Y should be added as a reference to project X. This is true regardless of whether project X is an executable or a static library. External LibrariesAll of the techniques discussed above assume that the referenced libraries are projects in your code solution. While this covers the majority of the cases in our class there are some functions that you will need to call from external libraries (e.g. Windows, Direct3D, OpenGL, Maya). The way that Visual Studio handles this for executables is nice and straightforward, but I haven't found a good way to handle things automatically for chains of static libraries. The following method is what I think is the least offensive alternative, and in our class we will use it for everything (static libraries and executables) to keep things consistent:
Doing the steps above will result in the same behavior that adding a reference to a local project does. Note that the external libraries we use in this class are actually dynamic libraries and not static libraries (there isn't any code from Windows that is directly embedded in your game executable, for example; it is loaded dynamically and shared with all other processes that are running). |
|