PhysicsFS/PhysFS++ Tutorial

This is a follow-up from a promise that I made in my tutorial video on designing an asset manager using SFML. That video can be found here.

This tutorial is centred around PhysFS++, a C++ wrapper for PhysicsFS. For the sake of the tutorial, it’s assumed that the reader is familiar with PhysicsFS and what it’s capable of. Described here is a workflow for simple use of the library. Anything more discrete is beyond the scope and will have to be ascertained by the reader on their own accord.

Lastly of note, PhysFS++ encapsulates PhysicsFS calls in a PhysFS namespace. The functions are global within this namespace and there are only a few classes that are provided. PhysFS++ further encapsulates key PhysicsFS constructs, notably those corresponding to archived files, into said classes that are derivatives of STL stream classes (a huge boon).

Like some other libraries, PhysicsFS requires explicit initialisation before it can be used. This is facilitated by a function named init. It takes one argument of type const char* and is semantically directed at a terminal invocation argument triaged through the much loved argv. However, this can be an empty string especially if you’re not expecting to handle terminal invocations. Thus, a very general call to init can be performed as such:

PhysFS::init (nullptr);

Right of the bat we have to mention a caveat here. From PhysFS++, there’s no way to assert the initialisation process of PhysicsFS. This is counter-intuitive to the upstream library which relies on the tried-and-true zero on failure, non-zero on success return values as sanity checks. Furthermore, while PhysFS++ implements C++ exceptions, the init function doesn’t throw any at all. Ostensibly, what one is left with is an unchecked call to init. Because one needs to compile PhysFS++ from the source, it is possible to modify the code, as I have done, to add a check to this call.

Once init has successfully completed, the next step is to mount an archive file into the virtual filesystem created by init. This is performed with the mount function. mount expects three arguments: the archive file on disk, a string specifying a mount point in the virtual filesystem, and a boolean which appends the mount point to the search path. One should place the archive file in the working directory for the binary file of their executable so PhysFS++ can see it. The second argument can be an empty string which would force root mounting, and the third can be true. Thus, for our example, if we assume we have an archive file named funphotos.zip on our disk in the binary’s working directory, we can issue a call to mount as such:

PhysFS::mount (“funphotos.zip”, “”, 1);

Unfortunately, as was the case with init, mount wraps an upstream function that adheres to the zero-or-nonzero return value paradigm that is outright dropped by PhysFS++ with no exception catering otherwise. Thus, if mount fails to mount the archive for whatever reason, it’ll be a little difficult to ascertain why; plan accordingly.

Assuming mount has returned properly, one can start to work with the files that are contained in the archive. At this point, you should begin working in the mentality of filesystem calls. It’s possible to have archive files with complex directory layouts which would require one to perform recursive searches. That being said, everything should be considered a file – even a directory. An analysis of the PhysicsFS and PhysFS++ APIs will provide for you the full breadth of your available capabilities so for the sake of brevity, only a select number of those will be touched here.

Enumeration of files in a directory can be performed with the enumerateFiles function. It takes as an argument a string which indicates the directory to use as a root for the enumeration. As a return it provides the caller with a vector of strings indicating the name of the file. For ease of use, a call to this to enumerate the files in root can be performed as such:

auto rootfiles = PhysFs::enumerateFiles (“/”);

To actually work with a file in the filesystem, one needs to use the PHYSFS_file ADT. This upstream ADT is encapsulated by one of three classes: PhysFS::ifstream, PhysFS::ostream, or PhysFS::fstream. Each of these is fantastic in that they encapsulate a PHYSFS_file ADT in a standard stream which means that one can now perform established stream operations on the file itself. Each class has its own use: fstream for reading files, ostream for writing to files, and ifstream for bidirectional file handling. In any case, any of these classes can be instantiated with a string argument that contains a fully qualified pathname to a file in the virtual filesystem that one wants to work with. For example, given that our virtual filesystem has a file named goofycats.png located at the path /textures/cats, we could instantiate a read file as such:

PhysFS::fstream gc (“/textures/cats/goofycats.png”);

Again, the underlying upstream call to open the file goes unchecked.

What you do from here is largely subjective relative to your program’s context. Say, for example (and this is actually pretty specific to my own use case), that you have a series of files of various formats in an archive that are being used in a video game program. The multimedia library you’re using should have ADTs that represent types of assets such as textures, fonts, etc. One could do some work to transpose the raw data of these streams into the aforementioned ADTs for use in the multimedia library. The following snippet of code, borrowed from one of my own projects, illustrates this. A PhysFS::fstream instance named f is created with a certain file. Following up is a char array named d is instantiated with the size of f. The read function of f is called to transpose the bytes from f into d. Then, d is used to instantiate an instance of sf::Music from SFML contained in a std::unordered_map:

code

This covers most the basic and general needs of users of PhysicsFS. Should you require anything else from it, you’d do well to read up on the Doxygen file of PhysicsFS or the source for PhysFS++. Lastly, when one is done with the library, you’ll need to call a deinitialization function called deinit:

PhysFS::deinit ();

Starting the SFML Journey with Fedora

I am a Fedora Fanboy. I love the distro. I will always recommend it to everyone. Despite that love, it seems like we have to cater our minds to how Fedora wants to do things. And believe me, it does things very differently when compared against Debian or any of its common derivatives. One major point of contention early on was getting used to how differently Apache works on Fedora opposed to Ubuntu. I actually prefer using Apache deployed on Ubuntu than I do Fedora. I fucking hate administering Apache on Fedora systems.

That being said, I wanted to take a few moments to discuss my adventure with SFML (Simple and Fast Multimedia Library) on Fedora from getting it installed, setting it up and actually compiling a simple source file with it.

First of all, I’m diving into SFML because there’s a project that I’ve been piecing together for a while and I think SFML fits the bill nicely based solely on research and reading the API. It also allows me to take a break from Java development and step back into C++ which is my favourite language. I feel all warm and fuzzy writing in it. I’ve always had 100% success getting SFML setup and configured on Windows computers with Visual Studio 2012. The obvious problems there are (A) I have to use a Windows computer (it’s bad enough that I’m surrounded by them at work and my laptop has Windows 7) and (B) while Visual Studio may be really pretty, I’ve never jived with how you have to use the GUI to configure all of the esoteric settings for the compiler and linker; it just feels clunky. I’d much rather type it out on the terminal or use a makefile.

Furthermore, as a bit of a primer, SFML is a multipurpose library for creating programs that need audio, graphics, networking or GUI resources in a cross-platform way using C++. The obvious use is video games but it can be applied to other types of programs as well.

Installation

Typically, when installing software libraries on Linux, you just hope and pray (if that’s your thing) that somewhere in your repositories that a pre-configured package exists for them. We shudder at the alternative method which is manually compiling and installing. I do anyway. So I was overwhelmingly pleased to see that the default repositories on Fedora did in fact have packages for SFML (SFML and SFML-devel). Cool!

First Attempt

For shits and giggles, I copied the source code that’s given on the SFML tutorial site and attempted to compile it (not link). I get my first ding.

#include <SFML/Graphics.hpp> not found

Fuck. Right off the bat, g++ can’t find a critical header that’s needed for the source to compile. So I did some digging. Knowing that library headers are typically under /usr/include, that’s where I started at. What a surprise! The headers got installed in a directory tree that went like this:

/usr/include/SFML-2.0/SFML/<blah-blah-blah>

Well that’s not going to work at all. So I moved the SFML directory out to /usr/include and removed the SFML-2.0 directory. Compilation success!

What About Linking?

This is usually the step where things get hairy when they go wrong. After getting a successful compile with an object file, I tried to link based on the steps in the tutorial.

g++ <file>.o -o <file> -lsfml-system -lsfml-window -lsfml-graphics

Result? ld can’t find any of the sfml-* libraries! Fan-fucking-tastic!

So there were a few things going on here that could have been causing the particular problem. First of all, I’m using a 64-bit version of Fedora. All libraries that are automatically installed by Yum, unless specified otherwise, will install the 64-bit version of the library. These files go under /usr/lib64. Some people have said that they’ll find them under /usr/local/lib64 but on my Fedora system they were under the former. It’s best to find out before you go rooting around and changing shit.

Second of all, ld wasn’t looking in /usr/lib64 for libraries. You can find out where ld is looking for libraries by looking at the /etc/ld.so.conf file. Although not entirely proper, I simply tacked the path to the end of the file and wrote it out. Once you do that, you need to run ldconfig (as root) to enforce the changes. If this step weren’t done, you’d have to keep linking with -L<path-to-library>/lib every time.

Lastly, even after all of that, my linking attempts were still failing. The reason this time? Name mismatches! That’s right the damn names of the libraries were wrong. The tutorial tells you to link to -lsfml-window. By default, I should have linked to -lsfml-window-2.0. Fucking bullshit. That went for any of the SFML shared object files. So I renamed those symlinks and took out the “-2.0” at the end so that -lsfml-window would work.

The End

After all that, I finally got a successful build of a demo SFML program and got the green circle in a 200×200 window. Why I had to go through all that trouble to get the trivial tutorial program to compile is beyond me but now that it’s working, I can move forward with my deeply laid plans to make shit happen.