The First Rule

Last night was bowling night. (164, 174, 129, in case you were wondering.) Thomas (my 9 year-old) goes with us and hangs out with us or in the arcade. Last night, his best friend went too, because his best friend’s mother was also bowling. So there we were at the bowling alley, having a good time.

Shortly before we were going to head home, Thomas and his best friend were running around (politely) and pretending to have some sort of ninja battle or Power Ranger fight or some other struggle against the powers of evil that kids do. The following dialog then ensued:

Me: Hey guys… this isn’t Fight Club, you know?
Thomas: The first rule of Fight Club is you don’t talk about Fight Club!
Me:

I laughed my head off.

And no, he hasn’t seen Fight Club. We were watching some kids show recently, some cartoon, and there was a bit of dialog something like “… the first rule of Fluffy Bunny Club is you don’t talk about Fluffy Bunny Club…” or something like that. I immediately cracked up, and so I had to explain to him why that was funny. I told him about that one scene in Fight Club and he obviously remembered it very well. Too well. I’m sure the other adults who were nearby now think I let him watch inappropriate films…

Objective-C Strings Are Not C Strings

I got bitten today by the fact that Objective-C strings in Cocoa programming are not the same things as plain old C strings. The problem is that Objective-C is essentially an object-oriented veneer on top of plain old C; sometimes it matters that you remember this, and other times it doesn’t. This was one of the times it mattered.

A little background. A while back I wrote and released ExportToArchive, a somewhat useful plugin for iPhoto. It allows you to select photos from your iPhoto library and export them into a few different archive formats. About three days after releasing it, I got an email from a guy who had just tried to export his entire library, 756 photos, into a single archive. He was perplexed because iPhoto just seemed to hang/lock up. The problem was that when I wrote the thing, I never considered that anyone would try to archive more than a few photos at a time. Thus, once you made your selections and started the export, I copied each file to a temporary directory, and then archived the copies. That works great for 10 or 20 photos, but not so well for 756.

The answer to that problem was not to copy the files, but to make a symlink of each photo into that temporary directory and then archive the files by dereferencing the links. It’s still going to take a while to archive the photos, but there will no longer be a copy phase, which should make things faster.

Which leads to today’s adventure. There’s not a native Obj-C or Cocoa method to create a symlink. There is a method on NSFileManager called linkPath:toPath:handler: but that creates a hard link, which won’t span file systems. So I was forced to use the C function symlink which takes two arguments: the source path and the destination path. This seemed easy. I would pass the absolute path name to the original file as the source argument, and the generated name for the link as the second. Easy-peasy.

Well, not really. Since symlink is a C function it, like most other C functions, tells you bugger-all about why a failure occurs. The return value when I tried to call it was -1 which means, “something bad happened.” I then had to consult the C value errno to get more info. The value of errno was 22 which, according to the header file errno.h means:

#define EINVAL 22 /* Invalid argument */

An invalid argument. OK. How about telling me which argument is invalid since I did, after all, pass in two arguments.

I tried escaping spaces and quoting the entire string, but nothing worked. Finally, it dawned on me: Objective-C strings are not C strings. symlink was expecting a plain old C string, but I was passing in something completely different: instances of the Obj-C class, NSString. So, the way to fix this was to pass in C strings, and how do you get C strings from NSString instances? Right, call UTF8string on them. Thus my call to symlink went from

rc = symlink(src, dest);

to

rc = symlink([src UTF8String], [dest UTF8String]);

and all seems to be working properly now.

I’m going to do a bit more testing on this, but I will probably release this new version tomorrow.

Photowalking

It used to be that going for a walk and taking your camera was called “going for a walk and taking your camera.” No longer. Apparently now it’s called Photowalking. So, to keep up with the cool kids, I will use the same name.

For the last two nights, I’ve been “photowalking” around my neighborhood. None of the photos I’ve taken have been “amazing” or “stunning” or “you’ve-gotta-see-this” quality, but I especially like this one of the trees silhouetted against the evening sky.

You can see the rest of the pictures at the following links: