Command-line Cocoa

It is possible to write command-line applications using Cocoa. However, you have to be careful. The only way to test such an app is by ssh’ing into your own box. You can’t just use the Terminal. Some APIs can only be called if they have access to the console or if root is running them. You won’t know that until you run your command-line app via ssh. if You get a message such as:
kCGErrorRangeCheck : Window Server communications from outside of session allowed for root and console user only
INIT_Processeses(), could not establish the default connection to the WindowServer.Abort
That is what’s going on.

The fix is simple, just don’t use the offending code. The offending code could be anything. I haven’t found a definitive list yet. Clearly anything related to the Window Server is out. Also verboten is anything related to the Process Manager.

To compensate, there is the little-known function “NSApplicationLoad” that will bootstrap enough of the Cocoa framework to run things that normally do not work until “awakeFromNib” in a GUI application. If you don’t want to call “NSApplicationMain”, go ahead and call “NSApplicationLoad”, create your own autorelease pool, and go forth on the command line.

MacOS X Dynamic Libraries

Dynamic libraries are difficult on any platform, MacOS X is no different. Basically, there are two kinds of dynamic libraries, those that a vendor installs, and those that you want to ship with an application.

If the dynamic libraries are installed by your OS vendor, no big deal. Those are the dynamic libraries you have available. If the dynamic libraries are installed by some other application, you may have a problem. If all you ever want to do is run programs, those libraries will be fine. If you want to develop your own programs, you will have problems. If the program you want to write depends on that vendor library, you are requiring that anyone who uses your program also has that library installed, preferably in that location. Even worse, you can’t reliably test your program because you now have a non-standard, system requirement that you can’t control. You could always use an installer to install your own system-level shared libraries. Users like that. I know I do. That is what is known as DLL-Hell.

For a developer, the way to solve this is by using the install_name_tool in MacOSX. This tool goes into an application and changes the path for a dynamic library. The idea is that, as one of your build scripts, you copy any required dynamic libraries into the application bundle of your program. Then, use install_name_tool to change the location of that library to @executable_path. Now, your application is linked against itself. It can be distributed to anyone.

Run “otool -L” against your executable to verify that any dynamic libraries are either system libraries or @executable_path libraries.

The downside of this is that a user could have 100 applications, each with the same dynamic library. Perhaps the OS is smart enough to only load one of them. I hope so. This is not quite DLL-Hell, more like DLL-Purgatory. There really is no better solution. You don’t want a user linking their own dynamic library with your app. You don’t want to link with a static library. That would make the application difficult to update and eliminate any possibility of OS efficiency.

Things today are designed to use dynamic libraries. No point in fighting it. Learn to live with it. Just don’t let that cause you to ship applications with odd dependencies or complicated installers. Bundle everything into a standalone app that is easily uninstalled.

Perhaps I should take my own advice and re-work Privoxy into an application bundle. That would be an excellent idea.

Unix executable inquiry tools

Once again today I found myself struggling to remember a certain obscure Unix command to inquire about what files were linked to an executable. That means it’s time to post to Etreblog again. So, for the record:

Utility Description
file
Display handy information about a file or library. MacOS X just tells the architectures while Linux provides some additional info.
ar t
List source files inside a static library
ldd
Print shared library dependencies. Not on MacOS X.
otool
Like ldd for MacOS X, only much more powerful.

Darwin versions for open-source development

I’m trying to support Intel in 10.4 and PPC in 10.2. I found the following table from Wikipedia very helpful:

Date Darwin release Mac OS X release
March 16, 1999 Darwin 0.1 Mac OS X Server 1.0
April 5, 2000 Darwin 1.0
April 13, 2000 Darwin 1.0.2 Mac OS X DP4
Darwin 1.2.1 Mac OS X public beta
April 13, 2001 Darwin 1.3.1 Mac OS X 10.0 to 10.0.4
October 2, 2001 Darwin 1.4.1 Mac OS X 10.1
Darwin 5.1 Mac OS X 10.1.1
Darwin 5.2 Mac OS X 10.1.2
Darwin 5.3 Mac OS X 10.1.3
Darwin 5.4 Mac OS X 10.1.4
Darwin 5.5 Mac OS X 10.1.5
September 23, 2002 Darwin 6.0.1 Mac OS X 10.2
October 28, 2002 Darwin 6.0.2 Mac OS X 10.2
Darwin 6.1 Mac OS X 10.2.1
Darwin 6.2 Mac OS X 10.2.2
Darwin 6.3 Mac OS X 10.2.3
Darwin 6.4 Mac OS X 10.2.4
Darwin 6.5 Mac OS X 10.2.5
Darwin 6.6 Mac OS X 10.2.6
Darwin 6.7 Mac OS X 10.2.7
Darwin 6.8 Mac OS X 10.2.8
October 24, 2003 Darwin 7.0 Mac OS X 10.3
Darwin 7.1 Mac OS X 10.3.1
Darwin 7.2 Mac OS X 10.3.2
Darwin 7.3 Mac OS X 10.3.3
Darwin 7.4 Mac OS X 10.3.4
Darwin 7.5 Mac OS X 10.3.5
Darwin 7.6 Mac OS X 10.3.6
Darwin 7.7 Mac OS X 10.3.7
Darwin 7.8 Mac OS X 10.3.8
April 15, 2005 Darwin 7.9 Mac OS X 10.3.9
April 29, 2005 Darwin 8.0 Mac OS X 10.4
May 16, 2005 Darwin 8.1 Mac OS X 10.4.1
July 12, 2005 Darwin 8.2 Mac OS X 10.4.2
October 31, 2005 Darwin 8.3 Mac OS X 10.4.3
January 10, 2006 Darwin 8.4 Mac OS X 10.4.4
February 14, 2006 Darwin 8.5 Mac OS X 10.4.5
April 3, 2006 Darwin 8.6 Mac OS X 10.4.6
August 7, 2006 Darwin 8.7 Mac OS X 10.4.7
September 29, 2006 Darwin 8.8 Mac OS X 10.4.8

A short primer on Objective-C++ exception handling and command line building

I found the following Objective-C try, catch, finally example recently. It also included a short blurb about building from the command line. I updated it a bit and here is my version.

As a C++ programmer, I’m not familiar with the “finally” phase. I wanted to verify that it really got called. Here is the code:

#import 

int exceptionTest(int argc);

int main(int argc, char * argv[])
  {
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  
  int result = exceptionTest(argc);
  
  NSLog(@"Result was %d", result);

  [pool release];

  return result;
  }

int exceptionTest(int argc)
  {
  @try 
    {
    if(argc > 1)
      @throw [NSException exceptionWithName: @"Throwing a test exception" 
        reason: @"Testing the @throw directive." userInfo: nil];

    NSLog(@"No exception this time");

    return 1;
    } 
  @catch (id theException) 
    {
    NSLog(@"%@", theException);

    return 2;
    } 
  @finally 
    {
    NSLog(@"This always happens.");
    }
  
  NSLog(@"Leaving function...");

  return 0;
  }

And here is another example that shows the finally clause really does get executed “out of bounds”:

#import 

#include 

int exceptionTest(int argc);

int main(int argc, char * argv[])
  {
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  
  int result = exceptionTest(argc);
  
  NSLog(@"Result was %d", result);

  [pool release];

  return result;
  }

template 
class Returner
  {
  public:
   
    Returner(T value) :
      myValue(value)
      {
      std::cout << "Creating returner with value " << myValue << std::endl;
      } 

    T returnValue(void)
      {
      std::cout << "Returning with value " << myValue << std::endl;
      return myValue;
      }

  private:

    T myValue;
  };

template 
Returner createReturner(T value)
  {
  return Returner(value);
  }

int exceptionTest(int argc)
  {
  @try 
    {
    if(argc > 1)
      @throw [NSException exceptionWithName: @"Throwing a test exception" 
        reason: @"Testing the @throw directive." userInfo: nil];

    NSLog(@"No exception this time");

    return createReturner(1).returnValue();
    } 
  @catch (id theException) 
    {
    NSLog(@"%@", theException);

    return createReturner(2).returnValue();
    } 
  @finally 
    {
    NSLog(@"This always happens.");
    }
  
  NSLog(@"Leaving function...");

  return createReturner(0).returnValue();
  }

To build it, do the following:

g++ -framework Cocoa -fobjc-exceptions etest.mm

Hmm… The “-framework” option seems pretty easy. Why did Codewarrior have such trouble with it? The whole concept seems easier on the command line.

Keep on vim’ing…

My .vimrc:

:syn on
:set number
set encoding=utf-8

I still use TextWranger if I need to edit 6 files at once. I can’t flip between files as easily in gvim. But at least I have Unicode working now.

NSProgressIndicator inside an NSTableView

I actually found something useful in CocoaDev. Well, about as useful as CocoaDev gets. Of course it didn’t work, but I was able to hack it up and it is working nicely now.

So, without further ado, here is how to put an NSProgressIndicator inside an NSTableView.

First, start off with ProgressCell.h

#import 

// Some handy definitions.
#define kControl @"control"

// An NSCell that contains a progress indicator.
@interface ProgressCell : NSCell
  {
  }

// Initialize.
- (id) init;

// Draw the cell.
- (void) drawInteriorWithFrame : (NSRect) cellFrame 
  inView: (NSView *) controlView;

@end

Next, add ProgressCell.mm (yeah, that’s .mm – Objective-C++ baby!)

#import "ProgressCell.h"

@implementation ProgressCell

// Constructor.
- (id) init
  {
  self = [super initImageCell: nil];
  
  return self;
  }

// Draw the cell.
- (void) drawInteriorWithFrame : (NSRect) cellFrame 
  inView: (NSView *) controlView
  {
  NSProgressIndicator * indicator = 
    [[self objectValue] objectForKey: kControl];
  
  // Removing subviews is tricky, if the progress bar gets removed when it gets
  // 100%, it could get re-created on resize. This is perhaps kludgy and should
  // be fixed.
  if([indicator doubleValue] < 100)
    {
    if(![indicator superview])
      [controlView addSubview: indicator];
	
    // Make the indicator a bit smaller. The setControlSize method
    // doesn't work in this scenario.
    cellFrame.origin.y += cellFrame.size.height / 3;
    cellFrame.size.height /= 1.5;
    
    [indicator setFrame: cellFrame];
    }
  }
  
@end

Now to use it, create an NSTableView. Add a column for the progress bars. Drag an NSImageCell into that column to turn it into an image column. Don't forget to setup your data source and maybe delegate.

In your controller's awakeFromNib, do this:

[[myTableView tableColumnWithIdentifier: kProgress] 
  setDataCell: [[ProgressCell alloc] init]];

I've got some handy macros for my column identifiers. They are:

// Some handy NSDictionary keys.
#define kPath      @"path"
#define kName      @"name"
#define kIcon      @"icon"
#define kProgress  @"progress"

My data source methods use an NSMutableArray. Here is the code:

// Get the number of rows in the table.
- (int) numberOfRowsInTableView: (NSTableView *) aTableView
  {
  return [myData count];
  }

// Get a table item value.
- (id) tableView: (NSTableView *) aTableView
    objectValueForTableColumn: (NSTableColumn *) aTableColumn
    row: (int) rowIndex
  {
  // Use those macros above for column identifiers.
  return [[myData objectAtIndex: rowIndex] 
    objectForKey: [aTableColumn identifier]];
  }

Now, to put something in myData so it will get displayed in the table, do the following:

// This icon stuff is just for a file icon. It doesn't have anything
// to do with the progress indicator. No point in removing it.

// See if there is an icon for this file.
NSImage * icon = [[NSWorkspace sharedWorkspace] iconForFile: path];
    
if(!icon)
    
  // No icon for actual file, try the extension.
  icon = [[NSWorkspace sharedWorkspace] iconForFileType: 
    [path pathExtension]];
     
NSProgressIndicator * progress = 
  [[[NSProgressIndicator alloc] init] autorelease];

// Unless you want it indeterminate, of course.  
[progress setIndeterminate: NO];

// This is an important plot point. You can't just put the control inside a dictionary.
// It complains about copyWithZone or something. You have to put the control inside
// a dictionary.
NSDictionary * progressData =
  [NSDictionary dictionaryWithObjectsAndKeys:
    progress, kControl,
    0];

// This dictionary is optional. You could do this differently.      
[myData addObject:     
  [NSDictionary dictionaryWithObjectsAndKeys:
    path, kPath,
    [path lastPathComponent], kName, 
    icon, kIcon, 
    progressData, kProgress,
    0]];

// Don't forget!  
[myTableView reloadData];

To update the control, use this snippet:

// Get the control.
NSProgressIndicator * progress = 
  [[[myData objectAtIndex: i] objectForKey: kProgress] 
    objectForKey: kControl];

[progress setDoubleValue: newValue];

Finally, to remove a row, there is an extra step:

// Get the control.
NSProgressIndicator * progress = 
  [[[myData objectAtIndex: i] objectForKey: kProgress] 
    objectForKey: kControl];
  
[progress removeFromSuperview];
  
// Now remove the row.    
[myData removeObjectAtIndex: i];

Unicode update

Perhaps I’m finally figuring out UTF-8, HTML, URLs, etc. But MacOS X’s built in URL handling and converting functions (CFURLCreateStringByAddingPercentEscapes and CFURLCreateStringByReplacingPercentEscapesUsingEncoding) seem to be working fine now. Sometimes it really is best to just hack something up and move on. Later, you can come back to your well-commented code after having learned a thing or two and get it all working the way it is supposed to.

Well, not all. MacOS X’s UTI architecture is another one destined for the dung pile. Apple has an impressive list of those. Let’s see if I can list just the ones I know of off the top of my head: OpenDoc, OpenTransport, Type/Creator codes, Resource Forks, Aliases, Volume Refererence Numbers, MacApp, and MPW (thought I’d forgotten about that one, didn’t you!). Then there are those that deserved better – rest in peace, Hypercard. And, finally, those that won’t die – one day, AppleScript, one day…

But all in all, I’ve had a productive few days. Best of all – I was able to delete some code. Bill Gates once said that measuring the quality of software by how many lines it has is like measuring an airplane by how much it weights. The analogy isn’t quite accurate, but his heart was in the right place. A better statement would be that you can measure the skill of a programmer, not by how many lines he or she writes, but by how many are deleted. A good programmer should almost always have negative code productivity. Try to sell that one to your matrix-level functional manager!