From Lazarus wiki
Jump to navigationJump to search

PasCocoa is the project to build object oriented bindings to use Cocoa in Pascal.

Objective-C to Pascal Bindings

There are 2 main versions of Objective-C, and thus of Objective-C headers: 1.0 and 2.0

Version 2.0 is only available on Mac OS X 10.5 or superior, making it too restrictive at the moment, and thus the available headers are a translation of 1.0 headers from a Mac OS X 10.4.9 machine.

Objective-C 1.0 Bindings

  • Available on: Mac OS X 10.0 and superior

Objective-C 2.0 Bindings

  • Available on: Mac OS X 10.5 and superior


<delphi> {

This example shows how to use the PasCocoa bindings to create a
NSAutoreleasePool, initialize the application global variable, create
a simple window without contents and attach a close handler to it that
exits the application.
Compilation of this example requires the following options:
-k-framework -kcocoa -k-lobjc
This example project is released under public domain
AUTHORS: Felipe Monteiro de Carvalho

} program simplewindow;

{$ifdef fpc}{$mode delphi}{$endif}


 objc, ctypes, FPCMacOSAll, AppKit, Foundation;


 Str_Window_Title = 'This is the title';
 Str_Window_Message = 'This is the message';


 { classes }
 pool: NSAutoreleasePool;
 MainWindow: NSWindow;
 MainWindowView: NSView;
 TextField: NSTextField;
 { strings }
 CFTitle, CFMessage: CFStringRef;
 { sizes }
 MainWindowRect, TextFieldRect: NSRect;


 {  Creates a AutoreleasePool for this thread. Every thread must have one }
 pool := NSAutoreleasePool.Create;
 { Creates the application NSApp object }
 NSApp := NSApplication.sharedApplication;
 { Creates a simple window }
 MainWindowRect.origin.x := 300.0;
 MainWindowRect.origin.y := 300.0;
 MainWindowRect.size.width := 300.0;
 MainWindowRect.size.height := 500.0;
 MainWindow := NSWindow.initWithContentRect(MainWindowRect,
   NSTitledWindowMask or NSClosableWindowMask or NSMiniaturizableWindowMask or NSResizableWindowMask,
   NSBackingStoreBuffered, NO);
 { Initializes the title of the window }
 CFTitle := CFStringCreateWithPascalString(nil, Str_Window_Title, kCFStringEncodingUTF8);
 { Adds a NSTextField with a string }
 CFMessage := CFStringCreateWithPascalString(nil, Str_Window_Message, kCFStringEncodingUTF8);
 TextFieldRect.origin.x := 0.0;
 TextFieldRect.origin.y := 200.0;
 TextFieldRect.size.width := 300.0;
 TextFieldRect.size.height := 100.0;
 TextField := NSTextField.initWithFrame(TextFieldRect);
 MainWindowView := NSView.CreateWithHandle(MainWindow.contentView);
 { Put's the window on the front z-order }
 { Enters main message loop };
 { Releases the AutoreleasePool for this thread }

end. </delphi>


svn co objc
svn co pascocoa


Creating a class which inherits from a Cocoa class

To create a class which inherits from a Cocoa class, one needs to create a normal class which inherits from any of the classes on the PasCocoa bindings and use the NSObject.CreateClassDefinition method to register that class on the Objective-C runtime before calling the NSObject constructor.


<delphi> uses foundation;


 { TMyController }
 TMyController = class(NSObject)
   { Extra binding functions }
   constructor Create; override;
   function getClass:; override;


 Str_TMyController = 'TMyController';


constructor TMyController.Create; begin

 { The class is registered on the Objective-C runtime before the NSObject constructor is called }
 if not CreateClassDefinition(Str_TMyController, Str_NSObject) then WriteLn('Failed to create objc class');
 inherited Create;
 { Insert other desired initialization here }


{ Called by the NSObject constructor to get the definition of our class.

 At this point the class is simply identifyed by it's name and must be already registered
 on the Objective-C runtime. }

function TMyController.getClass:; begin

 Result := objc_getClass(Str_TMyController);

end; </delphi>

Registering Pascal methods as Objective-c methods

Pascal methods aren't automatically available to Objective-C. They need to be first registered on the Objective-C runtime by overriding the AddMethods method and calling NSObject.AddMethod method for every method to be registered.


<delphi> </delphi>


General Roadmap

Component Status Details
Objective-C 1.0 Runtime Headers Working Mac OS X 10.0 or superior
Objective-C 2.0 Runtime Headers Not Implemented Mac OS X 10.5 or superior only
Automatic headers Parser Partially Implemented
Foundation Partially Implemented
AppKit Partially Implemented

Foundation Classes Roadmap

Component Status
NSAutoreleasePool Partially Implemented
NSGeometry Partially Implemented
NSObject Partially Implemented

AppKit Classes Roadmap

Component Status
NSActionCell Partially Implemented
NSAlert Partially Implemented
NSApplication Partially Implemented
NSButton Partially Implemented
NSButtonCell Partially Implemented
NSCell Partially Implemented
NSControl Partially Implemented
NSGraphics Partially Implemented
NSImage Partially Implemented
NSPanel Partially Implemented
NSTextField Partially Implemented
NSView Partially Implemented
NSWindow Partially Implemented
NSStatusBar Partially Implemented
NSStatusItem Partially Implemented

Implementation Details


The Cocoa headers contain several peculiarities that lead us to need a special structure for the bindings. First, several forward declarations of classes are done in a very unordently way. Pascal only accepts forward declarations of classes if they are all declared on the same type clause, and therefore a special session CLASSES is created on the include file.

The include file has a total of 3 separate sessions: HEADER, CLASSES and IMPLEMENTATION

A tipical include file should have this structure:

<delphi> {%mainunit appkit.pas} {

       Application Kit
       Copyright (c) 1997-2005, Apple Computer, Inc.
       All rights reserved.



//insert constants, records and other interface declarations with the exception of classes

{$endif} {$endif} {$ifdef CLASSES} {$ifndef NSSTATUSBAR_PAS_H} {$define NSSTATUSBAR_PAS_H}

//declaration of classes and forward declarations of classes

{$endif} {$endif} {$ifdef IMPLEMENTATION}

//insert implementation declarations here. The order is not important on the implementation, so don't use extra ifdefs.

{$endif} </delphi>



  • Inclusion of headers in other frameworks should be removed, because the each framework is mapped to a pascal unit, and therefore all include files of a used framework are already accessible. Inclusion of headers of the same file framework should become include clauses which will used a C-styled ifdef mechanism to resolve in which order the include files will be added. This mechanism works fairly well and keeps the structure of the include files similar to the original one.



  • Should include the same include files as the HEADERS section
  • All private members of classes should be removed