четверг, 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

Переменные окружения, влияющие на способ компиляции программ в GCC

C_INCLUDE_PATH - (для языка си) содержит список каталогов для поиска включаемых по директиве include заголовочных файлов, аналогична опции командной строки -isystem;
COMPILER_PATH - содержит список путей к каталогам, где компилятор проводит поиск своих подпрограмм, в случае ,если они не были найдены с помощью установки переменной GCC_EXEC_PREFIX;
CPATH - (для языков си, си++, объектный си) действует аналогично опции командной строки -I. Содержит список путей для поиска включаемых заголовочных файлов. Эти пути просматриваются после путей, указанных в -I;
CPLUS_INCLUDE_PATH - (для языка си++)содержит список каталогов для поиска включаемых по директиве include заголовочных файлов, аналогична опции командной строки -isystem. Эти каталоги просматриваются после каталогов, указанных в -isystem;
DEPENDENCIES_OUTPUT - препроцессор использует эту переменную для определения файла куда будут записываться правила зависимостей компоновки и цели, для которой создается отдельное правило. Аналогична сочетанию опций командной строки -MM, -MF, и -MT;
GCC_EXEC_PREFIX - используется для назначения префикса имен, вызываемых компилятором подпрограмм;
LANG - используется для указания компилятору набора кодировки, используемого для представления отдельных расширенных буквенных символов, текстовых строк и комментариев;
LC_ALL - замещает любые установки переменных LC_MESSAGES и LC_СTYPE;
LC_СTYPE - указывает способ кодировки расширенных буквенных знаков, имеющих мультибайтное представление;
LC_MESSAGES - указывает язык, используемый для выдачи компилятором диагностических сообщений;
LD_LIBRARY_PATH - применяется при выполнении программ. Предоставляет список путей, в которых программы во время своего запуска находят разделяемые библиотеки;
LD_RUN_PATH - применяется при выполнении программ. Предоставляет список путей, в которых программы во время своего запуска находят файл, содержащий имена символов и соответствующие им адреса. Аналогична опции -R утилиты ld;
LIBRARY_PATH - задает пути, где компоновщик ищет компоновочные сценарии и библиотеки, указанные опцией -l("эль"). Эти пути просматриваются после путей, заданных опцией -L;
OBJC_INCLUDE_PATH - (для объектного си) аналогична опции командной строки -isystem. Содержит список путей, где ищутся заголовочные include файлы. Эти каталоги просматриваются после каталогов, указанных в -isystem;
SUNPRO_OUTPUT - аналогична DEPENDENCIES_OUTPUT ?;
TMPDIR - содержит полный путь, где компилятор будет сохранять временные файлы;

четверг, 9 февраля 2012 г.

find, исключение директории из поиска

find - великолепная UNIX утилита. Но некоторые действия, которые надо выполнить с ее помощью, осуществляются с помощью не всегда легко понимаемого синтаксиса. Вот как, например, осуществить поиск файла myFile в директории myDir, но не заходя в поддиректорию subdirButNotMine:
# find /myDir \( -name myFile \) -print -o \( -name subdirButNotMine -prune \)
Помним, что вместо -name можно пользовать -path (перед subdirButNotMine).