Borkware Miniblog

September 29, 2007

Don’t Forget VoodooPad

Filed under: amosxp, programming, Random, work — Mark Dalrymple @ 3:57 pm

With all of the love and attention that Flying Meat’s Acorn is receiving, I figured I would remind folks about VoodooPad.

VoodooPad is a personal Wiki that lets you write stuff and link things around. When it sees words in CamelCapsStyle, it automatically turns it into a link to a new page where you can write more stuff. All pretty standard wiki stuff. It uses the OS X text engine so it has all of the standard word processing features you’ve come to expect, including stuff like tables and lists. This is especially nice because I get a lot of my emacs key bindings along for free. Muscle memory is a wonderful, wonderful thing.

Screen Capture of VoodooPad pro

There are a couple of things I love about VoodooPad : it gets out of my way. I type, I link, I paste in graphics. Gus has obviously paid a lot of attention to the fine details and the app just gets out of my way. It is also very stable. I don’t remember when my last crash was. It just works. Just about every Leopard update makes SnapZ pro freak out and I have to get get new license keys (and then usually something fails on the server side, and takes 20 minutes of dinking around to get a license). Omnigrackle‘s layers get confused and the PDF export dialog has a bug that makes it easy to corrupt your document. regularly crashes. But VoodooPad just keeps on chugging along. Oh, and it’s fast, too.

Some folks I know put everything into a single VoodooPad document and use it to store their life (or at least their brains). I typically have one VoodooPad document per project, which usually fall int into one of three broad categories:

Design Document : I have one where I keep my design notes for the Extreme Cross Stitch Design software I’m working on for the Spousal Overunit. I dump figures from OmniGrackle in there, and use class names as the currency of links. This makes it very easy to capture my thinking about the specifics of individual classes, as well as highlighting the interactions between classes. Sometimes I can go for a month or two between working on the App, so having all this stuff handy and interlinked makes it easy to reload my mental state. My winning IronCoder entry included a VoodooPad design document with all sorts of notes. (The entry was Race Against Time, if you’re really bored)

Data Dump and Organizer : I have another one where I keep all my notes, to-dos, transcriptions, and copies of interesting emails for the next edition of AMOSXP. You can see a screenie for this is over to the right. I blort in anything and everything I think might be interesting for the next edition. As I start chewing up a chapter, I have ready access to stuff to consider for exclusion (and stuff to nuke). Sometimes one topic (say an extension to a favorite object-oriented language) is too big for one chapter, so something like its automated memory management technique would make better sense living in the Memory chapter. So I can easily make a note in MemoryChap to say “go look over InThisSetOfNotes for these aspects of rubbish aggregation that would be interesting to talk about here”

Debugging Aid : For projects where I tend to do more debugging than design, I have a VoodooPad document that keeps my debugging notes. Usually for each non-trivial problem there’s a page with a dialog with myself. “So What’s the Problem Fool? Oh, Google Kipple is crashing when you frobulate the giznat. Does it happen all the time? No, just on the second launch. Maybe it’s the SpicyPonyHead user preference Hrm, could be” The dialog format lets me focus my thoughts by making explicit what the next useful piece of information might be, and it makes for easier reading when I need to revisit a bug or if I have to put it down for awhile and return to it later. The linky nature of a wiki makes it easy to put in different branches of investigation and let me revisit what I originally thought was a dead end, but might actually be the path to figuring out the real problem. Because Cocoa class names are CamelCapStyle, class names in stack trace become links. Ppaste in a stack trace and then link out to a class to jot down some relevant notes.

I’m a fan. Check it out.

September 27, 2007

Ten Tips for a (Slightly) Less Awful Resume

Filed under: Random, work — Mark Dalrymple @ 9:42 am

Steve Yegge knows hiring. His latest epistle is Ten Tips for a (Slightly) Less Awful Resume.

Rands also has a new article about The Button, the personality types you’ll run into during technical interviews.

September 13, 2007

C Callbacks in ObjC

Filed under: amosxp, irc, programming — Mark Dalrymple @ 11:23 am

It’s interesting to see common subjects come up in the IRC channels. When someone unfamiliar joins and asks the question “how do I put a method into a function pointer?”, 9 times out of 10 they’re actually wanting to use Cocoa with an existing C API that uses callbacks. A much better question would be “I’m using a C API that uses callbacks with Cocoa, how do I make it work?”

The Answer

You can’t use Objective-C methods as callbacks. Stop trying, you’ll just make yourself angrier. You have to bounce off of a regular C function, and use any “userData” or “info” mechanism in your C API to pass a pointer to your object.

So assuming you have a call SetDrawingCallback, which takes a function, but you actually want to draw using your objecty-goodness OblateSphereoid object, you would do something like this:

BWOblateSphereoid *egg = [[BWOblateSphereoid alloc] init];
SetDrawingCallback (drawingContext, /* context that wants to draw */
                    drawEggThunk, /* the function that the context will call */
                    egg);  /* arbitrary userData pointer */

Then in your callback function:

void drawEggThunk (DrawingContext *context, Rect areaToDraw, void *userData)
    BWOblateSphereoid *dealie = (BWOblateSphereoid *)userData;
    [dealie drawAnEggInRect: areaToDraw];
} // drawEggThunk

You are allowed to call Objective-C methods in a C function. You just need to make sure your file is compiled as Objective-C, whether you have a .m extension, or tell Xcode to compile it as Objective-C explicitly. If your callback API doesn’t let you pass in a userData pointer (a rock to hide your data under), you’ll have to put your object into some global location for your C function to find.

If you need to poke inside of the object directly, you can put this function inside of the @implementation block of your class, and then you can access instance variables with the C arrow operator. But that’s kind of naughty, so to preserve your Purity of Essence you should be using method calls on your object. End of Sermon. Here’s the evil:

@implementation OblateSphereoid
void drawEggThunk (DrawingContext *context, Rect areaToDraw, void *userData)
    BWOblateSphereoid *dealie = (BWOblateSphereoid *)userData;
    dealie->_frognatz = [NSColor plaidColor];
    // and more stuff.
} // drawEggThunk

@end // OblateSphereoid


So why can’t you just (somehow) get the address of -drawAnEggInRect: for the BWOblateSphereoid class and pass that for the drawing callback? The answer is a secret. Two of them, in fact.

When you use brackets in Objective-C to send a message to an object, the compiler is actually generating a call to the C function objc_msgSend (or to one of its variants, but let’s keep it simple):

id objc_msgSend(id self, SEL op, ...);

So something like [egg drawAnEggInRect: someRect] turns into:

objc_msgSend (egg, @selector(drawAnEggInRect:), someRect);

Which then calls drawAnEggInRect:, which under the covers boils down to something like this:

void drawAnEggInRect(id self, SEL selector, Rect someRect) ...

self and the selector are passed in as secret hidden parameters, and then any arguments for the method follow them. This is why you can’t just use the address for a method’s code in a C callback API. The library code invoking the callback will be wanting to put its own stuff in the first couple of arguments, which will cause all sorts of nifty explosions when Objective-C starts interpreting those as object pointers and selectors.

September 6, 2007

It’s Still Just C – arrays and pointers

Filed under: irc, programming — Mark Dalrymple @ 8:35 pm

Another fine day on IRC. An individual was stating that you couldn’t pass C arrays to Objective-C methods. That surprised me, so I wrote a little little command line program to check (the program is at lisppaste.) Of course, it turns out you can – Objective-C is still just C. And because it’s just C, you have the behavior of arrays and pointers being pretty much interchangeable.

For instance, you can pass a C array to a method:

- (void) ookie: (int *) snork {
    NSLog (@"%d %d %d", snork[0], snork[1], snork[2]);
} // ookie

Or use the [] syntax:

- (void) ookie2: (int[]) snork;

or use the explicit size syntax (which doesn’t really matter for 1-D arrays):

- (void) ookie3: (int[17]) snork;

And you can pass in pointers to pointers to pass back a resized array originally allocated by malloc:

- (void) ookie4: (int**) snork
         growTo: (int) elements {
    *snork = realloc(*snork, sizeof(int) * elements);
    (*snork)[0] = 55;
    NSLog (@"(%d) %d %d %d", sizeof(snork), (*snork)[0], (*snork)[1], (*snork)[2]);
} // ookie4

Passing in arrays of Objective-C types isn’t a problem either:

- (void) ookie: (NSString **) snork {
    NSLog (@"%@ %@", snork[0], snork[1]);
} // ookie

Just make sure your syntax is declaring the original array is good:

NSString *blargh[] = { @"oop", @"ack" };

(the original poster had confusion about Objective-C objects needing to be pointers, having a declaration of NSColor blargh[] = { ... }; and then stating that things aren’t possible)

It does go without saying that you should prefer NSArray, or another collection class, to naked C arrays. Sometimes you need to use the lower-level mechanisms, so the power (and pain) is there if needed.

September 3, 2007


Filed under: Random — Mark Dalrymple @ 5:21 pm

As part of my day-to-day work, I need to test my software with both admin accounts and non-admin accounts. Fast User Switching (FUS) is nice, for awhile, but it really started to get on my nerves. For one, I’d miss out on real-time entertainment from the company IRC channels. Then there’s the entering of passwords, and waiting for the Big Spinny Cube Effect. These are annoying, but livable.

The big thing is that in some wireless / VPN situations, the net connection would be available in one user but not the other; or the FUS act would disconnect me from the network or the VPN. And since I’m hitting internal resources for testing, this was totally Not Good.

BarryJ, (via my pal Mr. Machine Tool), pointed out that when you switch users with FUS, a window server and a pasteboard server are left running. This means that you can VNC from one user to another already logged-in user on the same machine.

It’s not perfect (the switched user might not be able to log to the console), and sometimes things lock up if I leave it running overnight, but it’s good enough for me to do my work with multiple user accounts and not have to actually FUS between them.

I use the Vine VNC server, and Chicken of the VNC client.

For the server, the changes from the default settings are setting a password, only allowing local connections (which requires SSH to be running). On the client, the host is localhost. So then FUS to the test user and crank up the server. FUS back to the primary account, and then start the VNC client.

September 2, 2007

Link Grab-bag

Filed under: programming — Mark Dalrymple @ 4:09 pm

In doing research and random surfing, I come across some intereting tidbits:

TN2124 : Debugging Magic – a must-read.

Improving your software with static analysis. Not really Shark-style static analysis, but more about using compiler flags to tweak the warning levels. I’m a firm believer in cranking up the warning levels using useful warnings (for instance, -Wunused-parameter is pretty much worthless)

LaunchD user agents are broken in Tiger

Also, the paper Setuid Demystified (PDF), while not OS X specific, does give some insight on how the unix setuid mechanism, how it works and its history.

Create a free website or blog at