Cześć, mam problem z organizacją kodu i zasadami jak to robić, większość tutoriali w internecie omawia podstawy tego zagadnienia. Ja potrzebuję dowiedzieć się jak podzielić kod na mniejsze pliki za pomocą dyrektywy include, i jak to pliki powinny się do siebie odnosić.
Mam np. program który wykorzystuje GTK+, mam więc funkcje:
budujące okna, przyciski itp.
funkcje przypięte odpowiadające na sygnały
funkcje realizujące zadania programu
Obecnie program podzielony jest na trzy pliki:
program.h - prototypy funkcji i struktur
program.c - ciała funkcji
#include"GNUmoku.h"
main.c - pętla main stąd kompiluję
#include"GNUmoku.h"
#include"GNUmoku.c"
A chciałbym mieć trzy pliki *.c np. gui.c, logika.c, sygnaly.c i czy do każdego musi być odpowiednik w postaci *.h? Ponadto chciałbym nie includować wszystkiego w main tylko jeszcze stworzyć dodatkowy nagłówek gdzie zaincluduje wszystkie pliki i ten jeden plik dam do maina. Jak porozmieszczać include żeby to wszystko łączyło się w jedną kupę i działało? Ponadto gdzie deklarować najlepiej zmienne globalne?
Pomysł z plikiem nagłówkowym biblioteki.h moim zdaniem nie jest najlepszy.
Powinieneś zrobić tak:
globals.h zawiera struct POLE
w plikach gui.h i konsola.h jeżeli jest w którymś użyta stuct POLE, to powinno być #include “globals.h”
w main.c dołączasz gui.h i konsola.h
Dla ułatwienia na przyszłość: linijka #include “plik.h” powoduje wklejenie zawartości danego pliku w tym miejscu. Nagłówki trzeba dołączać tak, żeby przed wykorzystaniem funkcji, struktur, zmiennych globalnych, itp, znalazły się ich deklaracje. W twoim przypadku przed deklaracją button_clicked nie było deklaracji struct POLE.
Wyjaśnienie: dwie pierwsze komendy (ważna jest opcja “-c”) kompilują pliki wejściowe do tzw. “object file”, odpowiednio main.o i gui.o. Jest to nic innego jak przerobienie kodu do binarki. Ale w tym momencie ten kod nie nadaje się do uruchomienia. Ostatnia linijka to jest konsolidacja, zwana też z angielskiego linkowanie. W tym momencie pliki .o zostają połączone w plik wykonywalny oraz dołączane są informacje o wymaganych bibliotekach dynamicznych. Korzystałeś kiedyś z make? Spróbuj tego:
Nie. Includowanie nagłówków nie może być błędne. Może co najwyżej być nadmiarowe (hail include guards) lub niepotrzebne.
Przykład:
gui.h
#ifndef GUI_H
#define GUI_H
#include /* Musi być. Inaczej GtkWidget będzie niezdefiniowane */
GtkWidget* create_window(void);
#endif /* GUI_H */
gui.c
/* W tym miejscu można dołączyć gtk/gtk.h ale po co, skoro i tak będzie w gui.h? */
#include "gui.h"
/* W tym miejscu można dołączyć gtk/gtk.h ale po co, skoro i tak zostało w gui.h? */
GtkWidget* create_window(void) {
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW(window), "test");
g_signal_connect(window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
return window;
}
main.c
#include /* Tutaj podobnie jak w gui.c nie jest to konieczne. */
#include "gui.h"
int main(int argc, char *argv[]) {
GtkWidget *window;
gtk_init (&argc, &argv);
window = create_window();
gtk_widget_show(window);
gtk_main();
return 0;
}