Skip to content

Archive

Tag: Objective-C

With no real alternative to Xcode on non-Mac platforms there is a real lack of a genuine development environment for Objective-C. With projects like GNUstep picking up the Objective-C runtime portion of the equation I’ve decided to try my hand at filling the other gap by creating a very simple IDE strictly for Objective-C. My goals were simple: create a basic IDE written in Objective-C that provides syntax highlighting, one button program compilation, and (if I could get it to work) some form of auto-complete or a suggestion system.

For my project I decided to target the cross-platform GTK+ because while Objective-C has the AppKit GUI libraries they just don’t look native enough for my liking. In addition because Objective-C is backwards compatible with all C code I could easily embed the GTK+ calls within wrapped objects and methods.

With a simple press of a button the program is compiled and run in the terminal just as you would expect.

As you can see I’ve so far succeeded in my simple goals. Although this project is still very much a work in progress I do hope to be able to release the source to it once I get it to a point where it is cleaned up and feature complete.

As sort of follow-up-in-spirit to my older post I decided to share a really straight forward way to use Objective-C to build GTK+ applications.

Objective-what?

Objective-C is an improvement to the iconic C programming language that remains backwards compatible while adding many new and interesting features. Chief among these additions is syntax for real objects (and thus object-oriented programming). Popularized by NeXT and eventually Apple, Objective-C is most commonly seen in development for Apple OSX and iOS based platforms. It ships with or without a large standard library (sometimes referred to as the Foundation Kit library) that makes it very easy for developers to quickly create fast and efficient programs. The result is a language that compiles down to binary, requires no virtual machines (just a runtime library), and achieves performance comparable to C and C++.

Marrying Objective-C with GTK+

Normally when writing a GTK+ application the language (or a library) will supply you with bindings that let you create GUIs in a way native to that language. So for instance in C++ you would create GTK+ objects, whereas in C you would create structures or ask functions for pointers back to the objects. Unfortunately while there used to exist a couple of different Objective-C bindings for GTK+, all of them are quite out of date. So instead we are going to rely on the fact that Objective-C is backwards compatible with C to get our program to work.

What you need to start

I’m going to assume that Ubuntu will be our operating system for development. To ensure that we have what we need to compile the programs, just install the following packages:

  1. gnustep-core-devel
  2. libgtk2.0-dev

As you can see from the list above we will be using GNUstep as our Objective-C library of choice.

Setting it all up

In order to make this work we will be creating two Objective-C classes, one that will house our GTK+ window and another that will actually start our program. I’m going to call my GTK+ object MainWindow and create the two necessary files: MainWindow.h and MainWindow.m. Finally I will create a main.m that will start the program and clean it up after it is done.

Let me apologize here for the poor code formatting; apparently WordPress likes to destroy whatever I try and do to make it better. If you want properly indented code please see the download link below.

MainWindow.h

In the MainWindow.h file put the following code:

#import <gtk/gtk.h>
#import <Foundation/NSObject.h>
#import <Foundation/NSString.h>

//A pointer to this object (set on init) so C functions can call
//Objective-C functions
id myMainWindow;

/*
* This class is responsible for initializing the GTK render loop
* as well as setting up the GUI for the user. It also handles all GTK
* callbacks for the winMain GtkWindow.
*/
@interface MainWindow : NSObject
{
//The main GtkWindow
GtkWidget *winMain;
GtkWidget *button;
}

/*
* Constructs the object and initializes GTK and the GUI for the
* application.
*
* *********************************************************************
* Input
* *********************************************************************
* argc (int *):    A pointer to the arg count variable that was passed
*             in at the application start. It will be returned
*            with the count of the modified argv array.
* argv (char *[]):     A pointer to the argument array that was passed in
*            at the application start. It will be returned with
*            the GTK arguments removed.
*
* *********************************************************************
* Returns
* *********************************************************************
* MainWindow (id):    The constructed object or nil
* arc (int *):        The modified input int as described above
* argv (char *[]):    The modified input array modified as described above
*/
-(id)initWithArgCount:(int *)argc andArgVals:(char *[])argv;

/*
* Frees the Gtk widgets that we have control over
*/
-(void)destroyWidget;

/*
* Starts and hands off execution to the GTK main loop
*/
-(void)startGtkMainLoop;

/*
* Example Objective-C function that prints some output
*/
-(void)printSomething;

/*
********************************************************
* C callback functions
********************************************************
*/

/*
* Called when the user closes the window
*/
void on_MainWindow_destroy(GtkObject *object, gpointer user_data);

/*
* Called when the user presses the button
*/
void on_btnPushMe_clicked(GtkObject *object, gpointer user_data);

@end

MainWindow.m

For the class’ actual code file fill it in as show below. This class will create a GTK+ window with a single button and will react to both the user pressing the button, and closing the window.

#import “MainWindow.h”

/*
* For documentation see MainWindow.h
*/

@implementation MainWindow

-(id)initWithArgCount:(int *)argc andArgVals:(char *[])argv
{
//call parent class’ init
if (self = [super init]) {

//setup the window
winMain = gtk_window_new (GTK_WINDOW_TOPLEVEL);

gtk_window_set_title (GTK_WINDOW (winMain), “Hello World”);
gtk_window_set_default_size(GTK_WINDOW(winMain), 230, 150);

//setup the button
button = gtk_button_new_with_label (“Push me!”);

gtk_container_add (GTK_CONTAINER (winMain), button);

//connect the signals
g_signal_connect (winMain, “destroy”, G_CALLBACK (on_MainWindow_destroy), NULL);
g_signal_connect (button, “clicked”, G_CALLBACK (on_btnPushMe_clicked), NULL);

//force show all
gtk_widget_show_all(winMain);
}

//assign C-compatible pointer
myMainWindow = self;

//return pointer to this object
return self;
}

-(void)startGtkMainLoop
{
//start gtk loop
gtk_main();
}

-(void)printSomething{
NSLog(@”Printed from Objective-C’s NSLog function.”);
printf(“Also printed from standard printf function.\n”);
}

-(void)destroyWidget{

myMainWindow = NULL;

if(GTK_IS_WIDGET (button))
{
//clean up the button
gtk_widget_destroy(button);
}

if(GTK_IS_WIDGET (winMain))
{
//clean up the main window
gtk_widget_destroy(winMain);
}
}

-(void)dealloc{
[self destroyWidget];

[super dealloc];
}

void on_MainWindow_destroy(GtkObject *object, gpointer user_data)
{
//exit the main loop
gtk_main_quit();
}

void on_btnPushMe_clicked(GtkObject *object, gpointer user_data)
{
printf(“Button was clicked\n”);

//call Objective-C function from C function using global object pointer
[myMainWindow printSomething];
}

@end

main.m

To finish I will write a main file and function that creates the MainWindow object and eventually cleans it up. Objective-C (1.0) does not support automatic garbage collection so it is important that we don’t forget to clean up after ourselves.

#import “MainWindow.h”
#import <Foundation/NSAutoreleasePool.h>

int main(int argc, char *argv[]) {

//create an AutoreleasePool
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

//init gtk engine
gtk_init(&argc, &argv);

//set up GUI
MainWindow *mainWindow = [[MainWindow alloc] initWithArgCount:&argc andArgVals:argv];

//begin the GTK loop
[mainWindow startGtkMainLoop];

//free the GUI
[mainWindow release];

//drain the pool
[pool release];

//exit application
return 0;
}

Compiling it all together

Use the following command to compile the program. This will automatically include all .m files in the current directory so be careful when and where you run this.

gcc `pkg-config –cflags –libs gtk+-2.0` -lgnustep-base -fconstant-string-class=NSConstantString -o “./myprogram” $(find . -name ‘*.m’) -I /usr/include/GNUstep/ -L /usr/lib/GNUstep/ -std=c99 -O3

Once complete you will notice a new executable in the directory called myprogram. Start this program and you will see our GTK+ window in action.

If you run it from the command line you can see the output that we coded when the button is pushed.

Wrapping it up

There you have it. We now have a program that is written in Objective-C, using C’s native GTK+ ‘bindings’ for the GUI, that can call both regular C and Objective-C functions and code. In addition, thanks to the porting of both GTK+ and GNUstep to Windows, this same code will also produce a cross-platform application that works on both Mac OSX and Windows.

Source Code Downloads

Source Only Package
File name: objective_c_gtk_source.zip
File hashes: Download Here
File size: 2.4KB
File download: Download Here

When Ubuntu 10.04 was released it represented the most modern incarnation of Canonical’s premier Linux desktop distribution. However not all things were better in this release. For myself I immediately noticed a problem while trying to install the gnustep-devel development libraries for GNUstep and Objective-C. I was greeted with this oh so lovely error message:

Some packages could not be installed. This may mean that you have requested an impossible situation or if you are using the unstable distribution that some required packages have not yet been created or been moved out of Incoming.
The following information may help resolve the situation:

The following packages have unmet dependencies:
gnustep-devel: Depends: gorm.app but it is not installable
E: Broken packages

So essentially I was left with the following choice: install the missing Gorm.app package from the repository (which wasn’t there) or don’t install gnustep-devel. Thankfully it was pointed out to me that I could perhaps see if the package still existed in the Debian repository instead. So off to http://www.debian.org/distrib/packages I went and after a quick search I found what I was looking for! I recalled reading somewhere that Ubuntu synchronizes with Debian testing (A.K.A. squeeze) at the start of every round of development, so I figured that would be the best package to grab. A short download and install later Gorm.app was finally on my system. With the dependencies now met it was a breeze to install the rest of the development files using a simple

sudo apt-get install gnustep-devel

And there you have it. By installing a single package from the Debian repository you too can get around the problem. For reference I have also filed a bug report with Ubuntu at Launchpad here.

For my iPhone Application Programming course I have become quite accustomed to using Objective-C; mostly because Apple strongly recommends requires that you write all of your code in it. Let me just begin by saying that Objective-C can be one of the most confusing and, at least at first glance, poorly designed programming languages that I have come across. Rather than using the standard C-like syntax of instance.method Objective-C uses a message passing syntax which looks a little something like [instance method]. Or… at least it used to. With the introduction of a new feature set Objective-C has also gained a ‘dot’ syntax similar to more classical languages. See what I mean about confusing?

So why on earth would anyone program in this language? Well in my opinion there are a number of good points that make Objective-C an ideal language to use for certain scenarios.

  • It is one of the few high-level languages that still compiles to native machine code.
  • It was built from the ground up as an object oriented programming language. This stands in contrast to C++ which effectively tries to tack OOP onto classic C.
  • Because it wasn’t trying to preserve any backwards compatibility, as was the case with C++, Objective-C did not inherit problems of an earlier language.
  • Objective-C can interface with standard C libraries and can even include C code inline for ease of use.
  • While Objective-C does make use of pointers, it does not suffer from the ‘pointer hell’ that C/++ does. What I mean by this is that it is more intelligent about its use of notation. For example, you don’t need to remember that you need to grab the memory address of an object (&) and then pass that as a pointer (*) to a function or, god forbid, make use of a pointer to a pointer (to a pointer to a pointer…).
  • Like C/++, Objective-C gives you complete control over memory management. However if you choose to you can enable automatic garbage collection for your code as well.
  • Unlike C’s #include pre-compile directive,which always forces a full copy of the source at be added at that point, Objective-C’s #import directive only adds the source once resulting in a smaller footprint.
  • When you finally do get Objective-C’s syntax it becomes a very straightforward and easy to read language.

Setup

On the Mac setup is basically as easy as installing Xcode. If you happen to use that platform I would highly recommend that you use Xcode as it is the absolute best Objective-C IDE. However for the rest of us we get to dig into the command-line!

Following this excellent guide I was able to install the required libraries and tools for both Windows and Linux. Essentially just follow the instructions on www.genustep.org, the open source implementation of NeXT’s Objective-C libraries, and you should be off to the races. Just remember that for Windows you only actually need to install GNUstep System and GNUstep Core (in that order!). Once everything is installed just open up your terminal (Linux) or start GNUstep Shell (Windows). This is where we will be compiling the programs from.

First program

Everyone needs a classic ‘hello, world!’ example program! Here is a very simple way to do this in Objective-C. Create a file called main.m (.m is like .c or .cpp) and place the following code in it:

//Link into the Foundation library which contains a lot of useful functions
#import <Foundation/Foundation.h>

//the main program function that will be run
int main(void)
{
     //log our string out to the console
     NSLog(@"hello, world!");

     //return success exit code
     return 0;
}

Then to compile it follow the instructions back on this post. I have found that for me the best Windows command line arguments are as follows:

gcc `gnusetup-config –objc-flags` -o [output name i.e. "test" produces "test.exe"] [input .m files i.e. "main.m"] -I /GNUstep/System/Library/Headers -L /GNUstep/System/Library/Libraries -lobjc -lgnustep-base -enable-auto-import

Your results may be different though. For the above example I used “hello” as the output name and “main.m” as the input .m files. On my machine this resulted in a file called hello.exe that was 478KB in size. If we change the first line of the program to #import <Foundation/NSString.h> instead and then recompile it we can shrink this down to 417KB. This is because we only really use the string library in our program, so importing the rest of Foundation is simply unnecessary.

Using objects

Rather than write a whole tutorial here I have created a little demonstration about the different ways you can use objects. While I don’t claim that this is the best way to do things, in fact if you read main.m I claim quite the opposite, it does give you an idea of the flexible nature of Objective-C’s OOP and memory management systems.

Download Here

Wrapping it up

Essentially what I am trying to get across here is that Objective-C is far from perfect, but it is quite a mature language and as such should probably have more wide-spread support. As a Computer Scientist who grew up in the post-C++ world, see: Java, I completely understand why many people are opting to use sandboxed or ‘virtualized’ programming languages, like .NET, Java and even things like PHP, over native languages like C/++, Objective-C or assembly. On the other hand there is something to be said for still writing code on the metal if for nothing else than the performance improvements you get by default. A lot of people are afraid of C’s pointers but if you can program in Java then I think you can easily program in Objective-C.

Give it a shot, you just might like it ;)