Archive for Лютий, 2009

GTK+ — 3. Керування позиціонуванням віджетів

неділя, Лютий 8th, 2009

У цій “лекції” я спробую пояснити, яким чином додавати на вікно нові віджети, та організувати їхнє бажане для вас позиціонування на ньому.

Власне, річ ось у чім — у GTK+, як і в усіх інших бібліотеках графічних віджетів для UNIX ви не можете (взагалі то можете, але про це, можливо, згодом) тупо накидати будь які віджети (кнопки, мітки, чекбокси, едітбокси, тощо) на форму, встановити зручні для вас розміри і місцерозташування цих віджетів, як, скажімо, у VLC.

UNIX’ові бібліотеки графічних віджетів використовують інших підхід до розміщення елементів на формі. Елементи розміщуються не лише по відношенню до верхнього лівого кута. Їхній розмір ще й задається по відношенню до висоти і ширини форми.

Тобто, якщо ви розмістите на формі лиш одну кнопку, то вона, за замовчуванням, матиме висоту і ширину рівну, відповідно, висоті і ширині форми. Не лякайтесь, ви звісно ж, можете чітко задати позицію та розміри кнопки, однак, даний підхід має низку переваг. Сподіваюсь, пояснити вам їх по ходу…

GtkFixed

Даний контейнер поміщає віджети у чітко фіксовані позиції і задає для них чітко фіксовані розміри. Даний контейнер не виконує автоматичну схему управління позицією та розміром віджетів. За звичай, він використовується досить рідко, наприклад, у програмах, де можна змінювати розміри віджетів або ж міняти їхню позицію.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <gtk /gtk.h>
 
 
int main(int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *fixed;
 
    GtkWidget *button1;
    GtkWidget *button2;
    GtkWidget *button3;
 
    gtk_init(&argc, &argv);
 
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "GtkFixed");
    gtk_window_set_default_size(GTK_WINDOW(window), 290, 200);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
 
    fixed = gtk_fixed_new();
    gtk_container_add(GTK_CONTAINER(window), fixed);
 
    button1 = gtk_button_new_with_label("Button");
    gtk_fixed_put(GTK_FIXED(fixed), button1, 150, 50);
    gtk_widget_set_size_request(button1, 80, 35);
 
    button2 = gtk_button_new_with_label("Button");
    gtk_fixed_put(GTK_FIXED(fixed), button2, 15, 15);
    gtk_widget_set_size_request(button2, 80, 35);
 
    button3 = gtk_button_new_with_label("Button");
    gtk_fixed_put(GTK_FIXED(fixed), button3, 100, 100);
    gtk_widget_set_size_request(button3, 80, 35);
 
    g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
 
    gtk_widget_show_all(window);
 
    gtk_main();
 
    return 0;
}
</gtk>

У даному прикладі, ми створюємо три кнопки, і поміщаємо їх на чітко вказані координати. Коли ми змінюємо розміри вікна, кнопки залишаються на своїх місцях.

Тут ми створюємо віджет контейнер GtkFixed:

fixed = gtk_fixed_new();

А тут, за допомогою функції gtk_fixed_put() поміщаємо першу кнопку у позиц

gtk_fixed_put(GTK_FIXED(fixed), button1, 150, 50);

gtkfixed

Read the rest of this entry »

Зневадження коду за допомогою strace

неділя, Лютий 8th, 2009

Ви коли небуть ломали собі голову над пошуком помилки? Помилки, яку ніяк не вдається знайти у джерельних текстах, але яка часто проявляється після компіляції і запуску програми. Знайомтесь: strace. strace — це утиліта, яка дозволяє вам трасувати системні виклики і сигнали конкретної команди. Якої команди? А які у вас є?

strace — вільне програмне забезпечення, що розповсюджується на умовах ліцензії, подібної до ліцензії BSD. Спершу утиліта була написана Полом Краненбургом (Paul Kranenburg) для SunOS за мотивами іншої утиліти для SunOS, trace. На Linux її портував Бранко Ланкестер (Branko Lankester), котрий, окрім цього, реалізував її підтримку в ядрі. У 1993, Рік Следкі (Rick Sladkey) об’єднав strace 2.5 для SunOS з другою версією strace для Linux, додавши при цьому багато можливостей truss(1) з SVR4. В результаті, з’явилася strace, котра працювала на обох платформах. Сьогодні, strace підтримується Уічертом Аккерманом (Wichert Akkerman) і Роландом МакҐрасом (Roland McGrath).

Трасування helloworld

Робота strace полягає у перехопленні і записі системних викликів, виконаних процесом, а також отриманих ним сигналів. Для кожного системного виклику, до стандартного файлу помилок, або ж до будь якого іншого заданого файлу, виводиться його ім’я, аргументи і код виклику. Як щодо кількох прикладів?

Щоб не ускладнювати роботу strace, я використав найпростішу з можливих програм.

1
2
3
4
5
6
7
#include <stdio .h>
 
main()
{
    printf("Hello World n");
}
</stdio>

Компілюємо її:

# gcc -o helloworld helloworld.c

Готово! Запускаємо: ./helloworld, і отримаємо на стандартний вихід:

Hello World

Виглядає надзвичайно просто. Тепер запустимо strace. strace протрасує, і виведе на stderr усі системні виклики і сигнали:

# strace ./helloworld

Вивід команди `strace ./helloworld`:

 1  execve("./helloworld", ["./helloworld"], [/* 22 vars */]) = 0
 2  uname({sys="Linux", node="knuth", ...}) = 0
 3  brk(0)                                  = 0x81f7000
 4  access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
 5  open("/etc/ld.so.cache", O_RDONLY)      = 3
 6  fstat64(3, {st_mode=S_IFREG|0644, st_size=73856, ...}) = 0
 7  old_mmap(NULL, 73856, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7fed000
 8  close(3)                                = 0
 9  open("/lib/tls/libc.so.6", O_RDONLY)    = 3
10  read(3, "177ELF111331 ?B00"..., 512) = 512
11  fstat64(3, {st_mode=S_IFREG|0755, st_size=1454835, ...}) = 0
12  old_mmap(0x40f000, 1215644, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x40f000
13  old_mmap(0x532000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x123000) = 0x532000
14  old_mmap(0x536000, 7324, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x536000
15  close(3)                                = 0
16  old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fec000
17  mprotect(0x532000, 4096, PROT_READ)     = 0
18  mprotect(0x40b000, 4096, PROT_READ)     = 0
19  set_thread_area({entry_number:-1 -> 6, base_addr:0xb7fec940, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
20  munmap(0xb7fed000, 73856)               = 0
21  fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 3), ...}) = 0
22  mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fff000
23  write(1, "Hello World n", 13)          = 13
24  munmap(0xb7fff000, 4096)                = 0
25  exit_group(13)                          = ?

Перше, що ми бачимо — це execve. execve() виконує програму, задану ім’ям файлу. Далі, uname() отримує ім’я і тип системи, яку я використовував для тесту. Після цього, наша програма запитує певну кількість пам’яті і мапи розміщення розділюваних бібліотек, необхідних для роботи, наприклад, динамічний завантажувач і libc. До всієї цієї інформації ми скоро повернемося, а поки подивимося, що відбувається далі. Рядок 23 виводу трасування, нарешті відкриває нам призначення нашої програми helloworld (як би ми не бачили джерельного коду): вивести у файловий дескриптор 1 (STDOUT), повідомити кількість байт у виведеній інформації та їх значення. Не складно здогадатися, що застосування трасування може допомогти вам відстежити у програмі конкретний виклик або сигнал. Чим же це корисно? Якщо ви пишете програму трохи більш складну, ніж helloworld.c, і вона дає збій, видаючи мінімум, або взагалі не видаючи інформації про те, що з нею сталося, трасування може вам допомогти виявити причину, яка викликає збій у процесі роботи.

Read the rest of this entry »

Code Review

четвер, Лютий 5th, 2009

“Doing reviews is the most important step you can
take to improve your software engineering performance”.

Watts Humphrey

Огляд або перевірка коду (Coding Review) — девелоперська практика попереднього перегляду і утверджувати коду іншими розробниками перед його заливкою на CVS.

Тобто, перед тим, як сабмітити свій код на cvs, ви даєте його на читання іншому програмістові. Той уважно (не бігло, а приділяючи цьому бодай 10-15 хвилин) його вичитує, вникає в логіку роботи, і намагається знайти у ньому, бодай очевидні помилки, або ж запропонувати інші, більш вдалі рішення вирішуваних вами задач. Якщо такі знаходяться, код повертається вам доопрацювання!

code_review_comic

Власне, навіщо це потрібно. Ну звісно ж, відповідь очевидна — у першу чергу, для підвищення якості коду. Адже, як відомо, одна голова добре, а дві — інколи, ліпше. Далеко не завжди певну роботу виконує програміст, який ліпше за усіх інших членів команди на ній знається. Та й, як би це банально, і до бридоти не серйозно й не звучало б, навіть початківці, зі своїм більше свіжим баченням та чистими від вбитих у голову шиблонів, можуть підкинути файну ідею.

Read the rest of this entry »

Get Adobe Flash playerPlugin by wpburn.com wordpress themes