четверг, 28 июня 2012 г.

Создание GTK+ приложения на Оbjective-C

Создаем файлы такого содержания:
MainWindow.h:


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

id myMainWindow;

@interface MainWindow : NSObject{
GtkWidget *winMain; //главное GtkWindow
GtkWidget *button;
}


-(id)initWithArgCount:(int *)argc andArgVals:(char *[])argv;
-(void)destroyWidget; /* Освобождает ранее занятые ресурсы Gtk виджетами */
-(void)startGtkMainLoop; /* Стартует главный цикл обработки сообщений GTK */
-(void)printSomething; /* Пример некой Objective-C функции */

/** Cи фунции обратного вызова (обработчики сообщений)*/

void on_MainWindow_destroy(GtkObject *object, gpointer user_data);/* Вызывается, когда закрывается главное окно приложения */
void on_btnPushMe_clicked(GtkObject *object, gpointer user_data); /* Вызывается, когда мы жмем кнопку */

@end



MainWindow.m:


#import "MainWindow.h"

@implementation MainWindow

-(id)initWithArgCount:(int *)argc andArgVals:(char *[])argv{
if (self = [super init]) { //вызываем init родительского класса
winMain = gtk_window_new (GTK_WINDOW_TOPLEVEL); //создаем главное окно приложения
gtk_window_set_title (GTK_WINDOW (winMain), "Ну привет");
gtk_window_set_default_size(GTK_WINDOW(winMain), 230, 150);
button = gtk_button_new_with_label ("Нажми её!");//создаем кнопку
gtk_container_add (GTK_CONTAINER (winMain), button);
g_signal_connect (winMain, "destroy", G_CALLBACK (on_MainWindow_destroy), NULL);
//привязываем обработчики сообщений
g_signal_connect (button, "clicked", G_CALLBACK (on_btnPushMe_clicked), NULL);
gtk_widget_show_all(winMain); //показываем
}

myMainWindow = self; //назначаем C-compatible указатель
return self; //возвращаем указатель на этот объект
}

-(void)startGtkMainLoop{
gtk_main(); //стартуем основной цикл обработки сообщений gtk
}

-(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)){
gtk_widget_destroy(button); //разрушаем кнопку
}
if(GTK_IS_WIDGET (winMain)){
gtk_widget_destroy(winMain); //разрушаем главное окно приложения
}
}

-(void)dealloc{
[self destroyWidget];
[super dealloc];
}

void
on_MainWindow_destroy(GtkObject *object, gpointer user_data){
gtk_main_quit(); //выходим из основного цикла обработки сообщений
}

void
on_btnPushMe_clicked(GtkObject *object, gpointer user_data){
printf("Button was clicked\n");
[myMainWindow printSomething]; //вызываем Objective-C функцию из Cи функции с помощью глобального указателяusing
}

@end


main.m:


#import "MainWindow.h"
#import <Foundation/NSAutoreleasePool.h>

int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
//создаем пул
gtk_init(&argc, &argv); //инициализируем gtk
MainWindow *mainWindow = [[MainWindow alloc] initWithArgCount:&argc andArgVals:argv];
//создаем GUI
[mainWindow startGtkMainLoop]; //стартуем главный цикл обработки сообщений GTK loop
[mainWindow release]; //освобождаем ресурсы занятые GUI
[pool release]; //освобождаем пул
return 0; //выходим из приложения
}


Компилируем это все из текущей директории следующей командой:
$ gcc `pkg-config --cflags --libs gtk+-2.0` -lgnustep-base -fconstant-string-class=NSConstantString MainWindow.m main.m -I /usr/include/GNUstep/ -L /usr/lib/GNUstep/ -std=c99 -O3

Запускаем на выполнение: ./a.out и видим:

Также выводиться сообщение в консоль.
Стоит ли говорить, что необходимо наличие установленных GTK и Objective-C? Необходимы пакеты gnustep-core-devel и libgtk2.0-dev. Все действия проводились на машине с установленной Debian Wheeze.
Да, еще надо сделать следующее. Если выскакивает ошибка "error: #error The current setting for native-objc-exceptions does not match that of gnustep-base ... please correct this." необходимо в файле /usr/include/GNUstep/GNUstepBase/GSConfig.h строку (221-я):
#define BASE_NATIVE_OBJC_EXCEPTIONS 1
заменить на:
#define BASE_NATIVE_OBJC_EXCEPTIONS 0

Комментариев нет: