Προβλήματα στη API της C.
Μπορεί να αντιμετωπίσετε μερικά προβλήματα στη βιβλιοθήκη που συσκευάζετε, ιδιαίτερα αν είναι ένα νέο έργο. Ιδού μερικά συνηθισμένα προβλήματα με λύσεις.
- G.6.1. Αδύνατη η προδήλωση δομών
- G.6.2. Έλλειψη ιδιοτήτων
G.6.1. Αδύνατη η προδήλωση δομών
By convention, structs are declared in glib/GTK+-style headers like so:
typedef struct _ExampleWidget ExampleWidget; struct _ExampleWidget { ... };
Ο πρόσθετος ορισμός τύπου επιτρέπει να χρησιμοποιηθεί η δομή σε μια κεφαλίδα χωρίς συμπερίληψη του πλήρους ορισμού της, απλά προδηλώνοντάς την, επαναλαμβάνοντας αυτόν τον τύπο ορισμού. Αυτό σημαίνει ότι δεν πρέπει να συμπεριλάβετε την κεφαλίδα της βιβλιοθήκης C στην κεφαλίδα της C++, κρατώντας την έξω από τη δημόσια API. Η gmmproc υποθέτει ότι αυτή η τεχνική χρησιμοποιήθηκε, έτσι θα δείτε σφάλματα μεταγλωττιστή αν αυτό δεν συμβαίνει.
This compiler error might look like this:
example-widget.h:56: error: using typedef-name 'ExampleWidget' after 'struct' ../../libexample/libexamplemm/example-widget.h:34: error: 'ExampleWidget' has a previous declaration here make[4]: *** [example-widget.lo] Error 1
example-widget.h:60: error: '_ExampleWidget ExampleWidget' redeclared as different kind of symbol ../../libexample/libexamplemm/example-widget.h:34: error: previous declaration of 'typedef struct _ExampleWidget ExampleWidget'
Αυτό είναι εύκολο να διορθώσετε στη βιβλιοθήκη C, γιαυτό στείλτε μια διόρθωση στον σχετικό συντηρητή.
G.6.2. Έλλειψη ιδιοτήτων
By convention, glib/GTK+-style objects have *_new() functions, such as example_widget_new() that do nothing more than call g_object_new() and return the result. The input parameters are supplied to g_object_new() along with the names of the properties for which they are values. For instance,
GtkWidget* example_widget_new(int something, const char* thing) { return g_object_new (EXAMPLE_TYPE_WIDGET, "something", something, "thing", thing, NULL); }
Αυτό επιτρέπει στους συνδυασμούς γλωσσών να υλοποιήσουν τα δικά τους ισοδύναμα (όπως κατασκευαστές C++), χωρίς τη χρήση της συνάρτησης *_new(). Αυτό είναι συχνά απαραίτητο, έτσι ώστε να μπορούν στην πραγματικότητα να δημιουργήσουν μια παράγωγη GType, για να προσθέσουν τα δικά τους άγκιστρα για τους χειριστές σήματος και τις εικονικές συναρτήσεις (vfuncs).
Τουλάχιστον, η συνάρτηση _new() δεν πρέπει να χρησιμοποιήσει καμία ιδιωτική API (συναρτήσεις που είναι μόνο σε αρχείο .c). Ακόμα κι αν δεν υπάρχουν συναρτήσεις, μπορούμε μερικές φορές να ξαναεφαρμόσουμε 2 ή 3 γραμμές κώδικα σε μια συνάρτηση _new() όσο αυτές οι γραμμές κώδικα χρησιμοποιούν API που είναι διαθέσιμη σε μας.
Another workaround is to add a *_construct() function that the C++ constructor can call after instantiating its own type. For instance,
GtkWidget* example_widget_new(int something, const char* thing) { ExampleWidget* widget; widget = g_object_new (EXAMPLE_TYPE_WIDGET, NULL); example_widget_construct(widget, "something", something, "thing", thing); } void example_widget_construct(ExampleWidget* widget, int something, const char* thing) { //Do stuff that uses private API: widget->priv->thing = thing; do_something(something); }
Η προσθήκη ιδιοτήτων και η επιβεβαίωση ότι αλληλεπιδρούν σωστά μεταξύ τους, είναι σχετικά δύσκολο να διορθωθεί στη βιβλιοθήκη C, αλλά είναι δυνατή, έτσι στείλτε ένα σφάλμα και προσπαθήστε να στείλετε μια διόρθωση στον σχετικό συντηρητή.