Archive

Posts Tagged ‘Objective-C’

CoreGTK 3.10.1 Released!

September 8th, 2015 No comments

The next version of CoreGTK, version 3.10.1, has been tagged for release today.

Highlights for this release:

  • Added some missing (varargs) GTK+ functions. This makes it easier to create widgets like the FileChooserDialog.

CoreGTK is an Objective-C language binding for the GTK+ widget toolkit. Like other “core” Objective-C libraries, CoreGTK is designed to be a thin wrapper. CoreGTK is free software, licensed under the GNU LGPL.

You can find more information about the project here and the release itself here.

This post originally appeared on my personal website here.




I am currently running a variety of distributions, primarily Linux Mint 17.
Previously I was running KDE 4.3.3 on top of Fedora 11 (for the first experiment) and KDE 4.6.5 on top of Gentoo (for the second experiment).

CoreGTK 3.10.0 Released!

August 20th, 2015 No comments

The next version of CoreGTK, version 3.10.0, has been tagged for release today.

Highlights for this release:

  • Move from GTK+ 2 to GTK+ 3
  • Prefer the use of glib data types over boxed OpenStep/Cocoa objects (i.e. gint vs NSNumber)
  • Base code generation on GObject Introspection instead of a mix of automated source parsing and manual correction
  • Support for GTK+ 3.10

CoreGTK is an Objective-C language binding for the GTK+ widget toolkit. Like other “core” Objective-C libraries, CoreGTK is designed to be a thin wrapper. CoreGTK is free software, licensed under the GNU LGPL.

You can find more information about the project here and the release itself here.

This post originally appeared on my personal website here.




I am currently running a variety of distributions, primarily Linux Mint 17.
Previously I was running KDE 4.3.3 on top of Fedora 11 (for the first experiment) and KDE 4.6.5 on top of Gentoo (for the second experiment).

CoreGTK now supports GTK+ 3 and is built from GObject Introspection

July 1st, 2015 No comments

It has been quite a while since the first release of CoreGTK back in August 2014 and in that time I’ve received a lot of very good feedback about the project, what people liked and didn’t like, as well as their wishlists for new features. While life has been very busy since then I’ve managed to find a little bit of time here and there to implement many of the changes that people were hoping for. As mentioned in my previous post here are the highlighted changes for this new version of CoreGTK:

Move from GTK+ 2 to GTK+ 3

GTK+ 3 is now the current supported widget toolkit and has been since February 2011. Now that GTK+ 3 is supported on all platforms (Windows, Mac and Linux) it makes sense to move over and take advantage of the updated features.

Additionally this allows for a natural break in compatibility with the previous release of CoreGTK. What that means for the end user is that I currently don’t have any plans on going back and applying any of these new ideas/changes to the old GTK+ 2 version of the code base, instead focusing my time and effort on GTK+ 3.

Prefer the use of glib data types over boxed OpenStep/Cocoa objects (i.e. gint vs NSNumber)

When originally designing CoreGTK I decided to put a stake in the ground and simply always favour OpenStep/Cocoa objects where possible. The hope was that this would allow for easier integration with existing Objective-C code bases. Unfortunately good intentions don’t always work out in the best way. One of the major pieces of feedback I got was to take a less strict approach on this and drop the use of some classes where it makes sense. Specifically keep using NSString instead of C strings but stop using NSNumber in place of primitives like gint (which itself is really just a C int). The net result of this change is far less boilerplate code and faster performance.

So instead of writing this:

/* Sets the default size of the window */
[window setDefaultSizeWithWidth: [NSNumber numberWithInt:400] andHeight: [NSNumber numberWithInt:300]];

you can now simply write this:

/* Sets the default size of the window */
[window setDefaultSizeWithWidth: 400 andHeight: 300];

Base code generation on GObject Introspection instead of a mix of automated source parsing and manual correction

The previous version of CoreGTK was, shall we say, hand crafted. I had written some code to parse header files and generate a basic structure for the Objective-C output but there was still quite a bit of manual work (days/weeks/months) involved to clean up this output and make it what it was. Other than the significant investment in time required to make this happen it was also prone to errors and would require starting back at square one with every new release of GTK+.

This time around the output is generated using GObject Introspection, specifically by parsing the generated GIR file for that library with the new utility CoreGTKGen. The proccess of generating new CoreGTK bindings using CoreGTKGen now takes just a couple of seconds and produces very clean and simple source code files. This is also really just the start as I’m sure there are plenty of improvements that can be made to CoreGTKGen to make it even better! Perhaps equally exciting is that once this process is perfected it should be relatively easy to adapt it to support other GObject Introspection supported libraries like Pango, Gdk, GStreamer, etc.

Let’s have an example shall we?

While there are a couple of good examples over at the Getting Started page of the Wiki and even within the CoreGTK repo itself I figured I would show something different here. It has always been my goal with this project to make it as easy as possible for existing Objective-C users to port their applications to GTK+. Perhaps you were previously using a widget toolkit like Cocoa on the Mac and now you want to release your application on more platforms. What better way than to keep your existing business logic and swap out the GUI (you do practice good MVC right? :P).

So going with this idea here is a tutorial of porting the “Start Developing Mac Apps Today” example from Apple’s developer website here. This application is incredibly simplistic but basically lets you set a “volume” value either by typing in a number in the text box at the top, moving the slider up and down, or pressing the Mute button. Regardless of which action you take the rest of the GUI is updated to match.

Step 1) Setup the GUI

For this I will be using GLADE as a replacement for the Xcode Interface Builder but you could always program your GUI by hand as well.

From the Apple website we are trying to re-create something that looks like this:

apple_exampleThankfully in GLADE this is relatively easy and I was able to do a quick and dirty mock up resulting in this:

glade_mockup

 

Step 2) Configure GUI signals (i.e. events)

GLADE also makes this easy, simply click on the widget, flip over to the Signals tab and type in your handler name.

textEntrySignal

Here are the ones I created:

  • window (GtkWindow)
    • Signal: destroy
    • Handler: endGtkLoop
  • entry (GtkEntry)
    • Signal: changed
    • Handler: takeValueForVolume
  • scale (GtkScale)
    • Signal: value-changed
    • Handler: sliderValueChanged
  • mute_button (GtkButton)
    • Signal: clicked
    • Handler: muteButtonClicked

Step 3) Create classes

Even though Cocoa and GTK+ don’t map exactly the same I decided to follow Apple’s conventions where it made sense just for consistency.

AppDelegate.h

#import "CoreGTK/CGTKEntry.h"
#import "CoreGTK/CGTKScale.h"

#import "Track.h"

@interface AppDelegate : NSObject
{
    CGTKEntry *textField;
    CGTKScale *slider;
    Track *track;
    BOOL updateInProgress;
}

@property (nonatomic, retain) CGTKEntry *textField;
@property (nonatomic, retain) CGTKScale *slider;
@property (nonatomic, retain) Track *track;

/* Callbacks */
-(void)mute;
-(void)sliderChanged;
-(void)takeValueForVolume;

/* Methods */
-(void)updateUserInterface;

-(void)dealloc;

@end

AppDelegate.m

#import "AppDelegate.h"

@implementation AppDelegate

@synthesize textField;
@synthesize slider;
@synthesize track;

/* Callbacks */
-(void)mute
{
    if(!updateInProgress)
    {
        updateInProgress = YES;
        
        [self.track setVolume:0.0];
    
        [self updateUserInterface];
        
        updateInProgress = NO;
    }
}

-(void)sliderChanged
{
    if(!updateInProgress)
    {
        updateInProgress = YES;
        
        [self.track setVolume:[self.slider getValue]];
    
        [self updateUserInterface];
        
        updateInProgress = NO;
    }
}

-(void)takeValueForVolume
{
    NSString *text = [self.textField getText];
    if([text length] == 0)
    {
        return;
    }
    
    if(!updateInProgress)
    {
        updateInProgress = YES;
        
        double newValue = [[self.textField getText] doubleValue];
    
        [self.track setVolume:newValue];
    
        [self updateUserInterface];
        
        updateInProgress = NO;
    }
}

/* Methods */
-(void)updateUserInterface
{
    double volume = [self.track volume];
    
    [self.textField setText:[NSString stringWithFormat:@"%1.0f", volume]];
    
    [self.slider setValue:volume];
}

-(void)dealloc
{
    [textField release];
    [slider release];
    [track release];
    [super dealloc];
}

@end

Track.h

/*
 * Objective-C imports
 */
#import <Foundation/Foundation.h>

@interface Track : NSObject
{
    double volume;
}

@property (assign) double volume;

@end

Track.m

#import "Track.h"

@implementation Track

@synthesize volume;

@end

Step 4) Wire everything up

In order to make everything work, load the GUI from the .glade file, connect the signals to the AppDelegate class, etc. we need some glue code. I’ve placed this all in the main.m file.

main.m

int main(int argc, char *argv[])
{    
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
    /* This is called in all GTK applications. Arguments are parsed
    * from the command line and are returned to the application. */
    [CGTK autoInitWithArgc:argc andArgv:argv];
        
    /* Create a builder to load GLADE file */
    CGTKBuilder *builder = [[CGTKBuilder alloc] init];
    
    if([builder addFromFileWithFilename:@"mac_app.glade" andErr:NULL] == 0)
    {
        NSLog(@"Error loading GUI file");
        return 1;
    }
    
    /* Create an AppDelegate to link to the GUI */
    AppDelegate *appDelegate = [[AppDelegate alloc] init];
    
    /* Get text field, wrapping returned Widget in new CGTKEntry */
    appDelegate.textField = [[[CGTKEntry alloc] initWithGObject:(GObject*)[[CGTKBaseBuilder 
        getWidgetFromBuilder:builder withName:@"entry"] WIDGET]] autorelease];
    
    /* Get slider, wrapping returned Widget in new CGTKScale */
    appDelegate.slider = [[[CGTKScale alloc] initWithGObject:(GObject*)[[CGTKBaseBuilder 
        getWidgetFromBuilder:builder withName:@"scale"] WIDGET]] autorelease];
    
    /* Create track class for AppDelegate */
    Track *track = [[Track alloc] init];
    appDelegate.track = [track autorelease];
    
    /* Pre-synchronize the GUI */
    [appDelegate updateUserInterface];
    
    /* Use signal dictionary to connect GLADE signals to Objective-C code */
    NSDictionary *dic = [[NSDictionary alloc] initWithObjectsAndKeys:
                     [CGTKCallbackData withObject:[CGTK class] 
                         andSEL:@selector(mainQuit)], @"endGtkLoop",
                         
                     [CGTKCallbackData withObject:appDelegate 
                         andSEL:@selector(mute)], @"muteButtonClicked",
                         
                     [CGTKCallbackData withObject:appDelegate 
                         andSEL:@selector(sliderChanged)], @"sliderValueChanged",
                         
                     [CGTKCallbackData withObject:appDelegate 
                         andSEL:@selector(takeValueForVolume)], @"takeValueForVolume",
                     nil];

    /* CGTKBaseBuilder is a helper class to maps GLADE signals to Objective-C code */
    [CGTKBaseBuilder connectSignalsToObjectsWithBuilder:builder andSignalDictionary:dic];
    
    /* Show the GUI */
    [[CGTKBaseBuilder getWidgetFromBuilder:builder withName:@"window"] showAll];
    
    /*
     * Release allocated memory
     */
    [builder release];
            
    /* All GTK applications must have a [CGTK main] call. Control ends here
     * and waits for an event to occur (like a key press or
     * mouse event). */
    [CGTK main];
    
    /*
     * Release allocated memory
     */    
    [appDelegate release];
    [pool release];
    
    // Return success
    return 0;
}

 

Step 5) Compile and run

coregtk_result

So while this is a very basic, quick and dirty example it does prove the point. As for CoreGTK this release is still under development as I try and flush out any remaining bugs but please give it a shot, submit issues or pitch in to help if you’re interested! You can find the CoreGTK project at http://coregtk.org.

Example Source Code
File name: mac_port_example.zip
File hashes: Download Here
License: (LGPL) View Here
File size: 5.3KB
File download: Download Here

This post originally appeared on my personal website here.




I am currently running a variety of distributions, primarily Linux Mint 17.
Previously I was running KDE 4.3.3 on top of Fedora 11 (for the first experiment) and KDE 4.6.5 on top of Gentoo (for the second experiment).

Adding GTK+ 3 support and building CoreGTK using GObject Introspection

May 3rd, 2015 No comments

It has been a while since I made any mention of my side project CoreGTK. I’m sure many people can relate that with life generally being very busy it is often hard to find time to work on hobby projects like this. Thankfully while that certainly has slowed the pace of development it hasn’t stopped it outright and now I am just about ready to show off the next update for CoreGTK.

First off thank you to everyone who took a look at the previous release. I received quite a few nice comments as well as some excellent feedback and hope to address quite a bit of that here. The feedback plus my own ideas of where I wanted to take the project defined the goal for the next release that I am currently working toward.

Goals for this release:

  • Move from GTK+ 2 to GTK+ 3
  • Prefer the use of glib data types over boxed OpenStep/Cocoa objects (i.e. gint vs NSNumber)
  • Base code generation on GObject Introspection instead of a mix of automated source parsing and manual correction

In order to explain the rationale behind these goals I figured I would address each point in more detail.

Move from GTK+ 2 to GTK+ 3

This one was pretty much a no-brainer. GTK+ 3 is now the current supported widget toolkit and has been since February 2011. Previously my choice to use GTK+ 2 was simply due to the fact that I wanted to make it as cross-platform as possible and at the time of release GTK+ 3 was not supported on Windows. Now that this has changed it only makes sense to continue forward using the current standard.

Additionally this allows for a natural break in compatibility with the previous release of CoreGTK. What that means for the end user is that I currently don’t have any plans on going back and applying any of these new ideas/changes to the old GTK+ 2 version of the code base, instead focusing my time and effort on GTK+ 3.

Prefer the use of glib data types over boxed OpenStep/Cocoa objects (i.e. gint vs NSNumber)

When originally designing CoreGTK I decided to put a stake in the ground and simply always favour OpenStep/Cocoa objects where possible. The hope was that this would allow for easier integration with existing Objective-C code bases. Unfortunately good intentions don’t always work out in the best way. One of the major pieces of feedback I got was to take a less strict approach on this and drop the use of some classes where it makes sense. Specifically keep using NSString instead of C strings but stop using NSNumber in place of primitives like gint (which itself is really just a C int). The net result of this change is far less boilerplate code and faster performance.

So instead of writing this:

/* Sets the border width of the window */
[window setBorderWidth: [NSNumber numberWithInt:10]];

you can now simply write this:

/* Sets the border width of the window */
[window setBorderWidth: 10];

Base code generation on GObject Introspection instead of a mix of automated source parsing and manual correction

The previous version of CoreGTK was, shall we say, hand crafted. I had written some code to parse header files and generate a basic structure for the Objective-C output but there was still quite a bit of manual work involved to clean up this output and make it what it was. Other than the significant investment in time required to make this happen it was also prone to errors and would require starting back at square one with every new release of GTK+. This time around the output is generated using GObject Introspection, specifically by parsing the generated GIR file for that library. Currently, and I must stress that there is still quite a bit of room for improvement, this allows me to generate CoreGTK bindings from scratch within an hour or so. With some of the final touches I have in mind the time required for this should hopefully be down to minutes (the auto-generation itself only takes seconds but it isn’t 100% yet). Better still once this process is perfected it should be relatively easy to adapt it to support other GObject Introspection supported libraries like Pango, Gdk, GStreamer, etc.

So where is this new release?

I am getting closer to showing off this new code but first I have to do a bit of cleanup on it. This hopefully won’t take too much longer and to show you how close I am here is a screenshot of CoreGTK running using GTK+ 3.

coregtk-3

This post originally appeared on my personal website here.




I am currently running a variety of distributions, primarily Linux Mint 17.
Previously I was running KDE 4.3.3 on top of Fedora 11 (for the first experiment) and KDE 4.6.5 on top of Gentoo (for the second experiment).

CoreGTK 2.24.0 Released!

August 4th, 2014 No comments

The initial version of CoreGTK, version 2.24.0, has been tagged for release today.

Features include:

  • Targets GTK+ 2.24
  • Support for GtkBuilder
  • Can be used on Linux, Mac and Windows

CoreGTK is an Objective-C language binding for the GTK+ widget toolkit. Like other “core” Objective-C libraries, CoreGTK is designed to be a thin wrapper. CoreGTK is free software, licensed under the GNU LGPL.

You can find more information about the project here and the release itself here.

This post originally appeared on my personal website here.




I am currently running a variety of distributions, primarily Linux Mint 17.
Previously I was running KDE 4.3.3 on top of Fedora 11 (for the first experiment) and KDE 4.6.5 on top of Gentoo (for the second experiment).

CoreGTK

January 28th, 2014 2 comments

A while back I made it my goal to put together an open source project as my way of contributing back to the community. Well fast forward a couple of months and my hobby project is finally ready to be shown the light of day. I give you… CoreGTK

CoreGTK is an Objective-C binding for the GTK+ library which wraps all objects descending from GtkWidget (plus a few others here and there). Like other “core” Objective-C libraries it is designed to be a very thin wrapper, so that anyone familiar with the C version of GTK+ should be able to pick it up easily.

However the real goal of CoreGTK is not to replace the C implementation for every day use but instead to allow developers to more easily code GTK+ interfaces using Objective-C. This could be especially useful if a developer already has a program, say one they are developing for the Mac, and they want to port it to Linux or Windows. With a little bit of MVC a savvy developer would only need to re-write the GUI portion of their application in CoreGTK.

So what does a CoreGTK application look like? Pretty much like a normal Objective-C program:

/*
 * Objective-C imports
 */
#import <Foundation/Foundation.h>
#import "CGTK.h"
#import "CGTKButton.h"
#import "CGTKSignalConnector.h"
#import "CGTKWindow.h"

/*
 * C imports
 */
#import <gtk/gtk.h>

@interface HelloWorld : NSObject
/* This is a callback function. The data arguments are ignored
 * in this example. More callbacks below. */
+(void)hello;

/* Another callback */
+(void)destroy;
@end

@implementation HelloWorld
int main(int argc, char *argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    /* We could use also CGTKWidget here instead */
    CGTKWindow *window;
    CGTKButton *button;

    /* This is called in all GTK applications. Arguments are parsed
    * from the command line and are returned to the application. */
    [CGTK autoInitWithArgc:argc andArgv:argv];

    /* Create a new window */
    window = [[CGTKWindow alloc] initWithGtkWindowType:GTK_WINDOW_TOPLEVEL];

    /* Here we connect the "destroy" event to a signal handler in 
     * the HelloWorld class */
    [CGTKSignalConnector connectGpointer:[window WIDGET] 
        withSignal:@"destroy" toTarget:[HelloWorld class] 
        withSelector:@selector(destroy) andData:NULL];

    /* Sets the border width of the window */
    [window setBorderWidth: [NSNumber numberWithInt:10]];

    /* Creates a new button with the label "Hello World" */
    button = [[CGTKButton alloc] initWithLabel:@"Hello World"];

    /* When the button receives the "clicked" signal, it will call the
     * function hello() in the HelloWorld class (below) */
    [CGTKSignalConnector connectGpointer:[button WIDGET] 
        withSignal:@"clicked" toTarget:[HelloWorld class] 
        withSelector:@selector(hello) andData:NULL];

    /* This packs the button into the window (a gtk container) */
    [window add:button];

    /* The final step is to display this newly created widget */
    [button show];

    /* and the window */
    [window show];

    /* All GTK applications must have a [CGTK main] call. Control ends here
     * and waits for an event to occur (like a key press or
     * mouse event). */
    [CGTK main];

    [pool release];

    return 0;
}

+(void)hello
{
    NSLog(@"Hello World");
}

+(void)destroy
{
    [CGTK mainQuit];
}
@end
Hello World in action

Hello World in action

And because Objective-C is completely compatible with regular old C code there is nothing stopping you from simply extracting the GTK+ objects and using them like normal.

// Use it as an Objective-C CoreGTK object!
CGTKWindow *cWindow = [[CGTKWindow alloc] 
    initWithGtkWindowType:GTK_WINDOW_TOPLEVEL];

// Or as a C GTK+ window!
GtkWindow *gWindow = [cWindow WINDOW];

// Or even as a C GtkWidget!
GtkWidget *gWidget = [cWindow WIDGET];

// This...
[cWindow show];

// ...is the same as this:
gtk_widget_show([cWindow WIDGET]);

You can even use a UI builder like GLADE, import the XML and wire up the signals to Objective-C instance and class methods.

CGTKBuilder *builder = [[CGTKBuilder alloc] init];
if(![builder addFromFile:@"test.glade"])
{
    NSLog(@"Error loading GUI file");
    return 1;
}

[CGTKBuilder setDebug:YES];

NSDictionary *dic = [[NSDictionary alloc] initWithObjectsAndKeys:
                 [CGTKCallbackData withObject:[CGTK class] 
                     andSEL:@selector(mainQuit)], @"endMainLoop",
                 [CGTKCallbackData withObject:[HelloWorld class] 
                     andSEL:@selector(hello)], @"on_button2_clicked",
                 [CGTKCallbackData withObject:[HelloWorld class] 
                     andSEL:@selector(hello)], @"on_button1_activate",
                 nil];

[builder connectSignalsToObjects:dic];

CGTKWidget *w = [builder getWidgetWithName:@"window1"];
if(w != nil)
{
    [w showAll];
}

[builder release];

So there you have it that’s CoreGTK in a nutshell.

There are a variety of ways to help me out with this project if you are so inclined to do so. The first task is probably just to get familiar with it. Download CoreGTK from the GitHub project page and play around with it. If you find a bug (very likely) please create an issue for it.

Another easy way to get familiar with CoreGTK is to help write/fix documentation – a lot of which is written in the source code itself. Sadly most of the current documentation simply states which underlying GTK+ function is called and so it could be cleaned up quite a bit.

At the moment there really isn’t anything more formal than that in place but of course code contributions would also be welcome!

Update: added some pictures of the same program running on all three operating systems.

Hello World on Windows

Hello World on Windows

Hello World on Mac

Hello World on Mac

Hello World on Linux

Hello World on Linux

This post originally appeared on my personal website here.




I am currently running a variety of distributions, primarily Linux Mint 17.
Previously I was running KDE 4.3.3 on top of Fedora 11 (for the first experiment) and KDE 4.6.5 on top of Gentoo (for the second experiment).

Create a GTK+ application on Linux with Objective-C

December 8th, 2010 8 comments

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

Originally posted on my personal website here.




I am currently running a variety of distributions, primarily Linux Mint 17.
Previously I was running KDE 4.3.3 on top of Fedora 11 (for the first experiment) and KDE 4.6.5 on top of Gentoo (for the second experiment).

Fixing gnustep-devel in Ubuntu 10.04

May 17th, 2010 No comments

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.

Originally posted on my personal website here.




I am currently running a variety of distributions, primarily Linux Mint 17.
Previously I was running KDE 4.3.3 on top of Fedora 11 (for the first experiment) and KDE 4.6.5 on top of Gentoo (for the second experiment).