Last night I was thinking about simple concepts we use everyday to communicate. I'm very unpleased to not have a fitting example, but I think I'll be able to let you understand.
Sometimes happens to tell someone: <<Have you watched Star Trek?>> and our mate will answer: <<Do you mean the movie or the show?>> This is a very silly example but sometimes things need to be qualified to be exact.
OK, let's go back to Tagsistant and your full episode collection of star trek tv shows and movies and video games and whatever. It would be very nice to have category tagging in Tagsistant to tell that the first are "tvshow:startrek", the second are "movie:startrek" and the third are "videogames:startrek".
So we'll be able to find everything about Star Trek with an usual
$ ls tags/startrek/
query, but we'll also find all Star Trek tv shows by
$ ls tags/tvshow:startrek/
and also all our tv shows by searching for
$ ls tags/tvshow:/
(note the colon at the end).
One of the coolest feature of POSIX systems is dynamic loading of libraries
and plugins. Everything is managed by dlopen() and its companions.
Loading at runtime means just:
- locating the library file
- use dlopen() to get a pointer to the library
- use dlsym() to get a pointer for each function inside the library you need
- use dlclose() to keep you code clean and help make the world a better place to live in ;-)
MacOS X and GNU/Linux both provide the same interface and code is straight portable. So, why I'm writing about that? Because you may have inserted in your code some check to locate the plugins of your application, dropping other files present in the same directory.
For example, Tagsistant uses /usr/local/lib/
as default path to store its plugins, which are named
libtagsistant_<mimetype>.so under GNU/Linux. And here enters
the matter: under MacOS X the extension is ".dylib" instead of
".so"!
The code which locates the plugins is the following:
#define TAGSISTANT_PLUGIN_PREFIX "libtagsistant_"
char *needle = strstr(de->d_name, TAGSISTANT_PLUGIN_PREFIX); if ((needle == NULL) || (needle != de->d_name))
continue;
needle = strstr(de->d_name, ".so");
if ((needle == NULL) || (needle != de->d_name + strlen(de->d_name) - 3))
continue;
This fragment is inserted into a cycle which traverse the whole plugins
list, that's why uses continue in reaction to failure. Number 3 in
last if statement is the length of ".so" string. This code compiles cleanly
under MacOS X but fails. After discovering the extension difference, I've
changed this code as:
#define TAGSISTANT_PLUGIN_PREFIX "libtagsistant_" char *needle = strstr(de->d_name, TAGSISTANT_PLUGIN_PREFIX); if ((needle == NULL) || (needle != de->d_name)) continue; #ifdef MACOSX # define PLUGIN_EXT ".dylib" #else
# define PLUGIN_EXT ".so"
#endif needle = strstr(de->d_name, PLUGIN_EXT); if ((needle == NULL) || (needle != de->d_name + strlen(de->d_name) - strlen(PLUGIN_EXT))) /> continue;
And now, finally, Tagsistant locates and loads its plugins!