इन कि तुम सच में जब तक आप कुछ बहुत ही निम्न स्तर कोड पर काम करने की कोशिश कर रहे हैं के बारे में परवाह करने की जरूरत के केवल दो GValue और GParamType
हैं
मैं शुरू करेंगे GParamType
GParamType
साथ के लिए है एक GObject के साथ एक संपत्ति रजिस्टर करने के लिए इस्तेमाल किया। कहें, उदाहरण के लिए, मेरे पास एक गोब्जेक्ट सबक्लास है जिसे व्यक्ति कहा जाता है, और मैं चाहता हूं कि इसमें दो गुण हों: नाम और आयु। class_init
समारोह में मैं की तरह तो
{
GParamSpec *pspec;
. . .
pspec = g_param_spec_string ("name", "Name", "The name of the person", "", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_NAME, pspec);
pspec = g_param_spec_int ("age", "Age", "The age of the person", 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_AGE, spec);
. . .
}
अब आप उन गुणों पर g_object_get
या g_object_set
कॉल कर सकते हैं इन रजिस्टर होता है और प्रणाली है कि यह कैसे संभाल करने के लिए
char *name;
int age;
g_object_set (G_OBJECT (person), "name", "Steve", "age", 37, NULL);
g_object_get (G_OBJECT (person), "name", &name, "age", &age, NULL);
g_print ("%s is %d years old\n", name, age);
// And because the type system knows when a property is a string, it knows how to give
// you a copy of the string, so you need to free it once you've finished with it
g_free (name);
विभिन्न मापदंडों यहाँ समझाया गया है पता चल जाएगा: GParamSpec सभी मानक प्रकारों के लिए GValue प्रकार हैं: तार, बूल, इन्स आदि, और कुछ अन्य पुस्तकालय जैसे कि जीस्ट्रीमर अपने स्वयं के कस्टम लोगों को पंजीकृत करेंगे।
GObjectClass पर गुण स्थापित करने के बाहर आप बहुत मुश्किल से ही GParamSpec से निपटने के लिए की जरूरत है। दो मुख्य अवसरों उन्हें प्रदर्शित करने वाले GObjectClass सेट/get_property तरीकों में है और GObject सूचित संकेत। यह पता लगाने के लिए g_param_spec_get_name
फोन करके जो संपत्ति संकेत सूचित प्राप्त हुआ है, पिछले मामले में उपयोगी है, लेकिन वास्तव में यह एक अधिक विशिष्ट इसलिए जैसे संकेत सूचित उपयोग करना बेहतर है:
g_signal_connect (person, "notify::name", G_CALLBACK (name_changed_cb), NULL);
g_signal_connect (person, "notify::age", G_CALLBACK (age_changed_cb), NULL);
बजाय
g_signal_connect (person, "notify", G_CALLBACK (something_changed_cb), NULL);
कभी-कभी आप अपनी खुद की संरचनाएं बनाना और गुणों के लिए उन लोगों का उपयोग करना चाह सकते हैं। उदाहरण के लिए यदि मेरे पास
struct _PersonDetails {
char *name;
int age;
}
और व्यक्ति ऑब्जेक्ट पर दो गुण रखने की बजाय, मैं चाहता था कि कोई "विवरण" कहलाता हो। GLib प्रकार प्रणाली अपने कस्टम struct _PersonDetails
से निपटने के लिए कैसे पता नहीं है तो मैं इसके लिए एक बॉक्स्ड प्रकार बनाने के लिए की आवश्यकता होगी, ताकि यह पता था कि कैसे सही ढंग से कॉपी करने के लिए/नि: शुल्क संरचना के रूप में यह चारों ओर GLib internals पारित कर दिया है। और यहीं GValue
में आता है।
GValue
विभिन्न प्रकार ताकि वे नकल की और सही ढंग से मुक्त कर दिया (अगर वे करने की आवश्यकता है) किया जा सकता है के मूल्यों लपेटकर के लिए है, और इसलिए है कि जेनेरिक कार्यों के लिए इस्तेमाल किया जा सकता है।
उदाहरण के लिए, GObjectClass विधि set_property
void set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
इसका मतलब है कि किसी भी प्रकार जो एक GValue द्वारा दर्शाया जा सकता में पारित किया जा सकता है और इस तरह set_int_property, set_string_property, set_bool_property के रूप में विशिष्ट कार्य नहीं कर रहे हैं के प्रोटोटाइप है की आवश्यकता है।
इसका यह भी अर्थ है कि g_object_set
और g_object_get
फ़ंक्शन को पारित करने वाले पैरामीटर से निपटने का तरीका पता है क्योंकि यह जानता है कि संपत्ति "नाम" एक स्ट्रिंग प्रकार के रूप में पंजीकृत है, और इसमें प्रतिलिपि/उस स्ट्रिंग को मुक्त करें।
GValue के बारे में अधिक पाया जा सकता है - Generic values
GLib प्रकार प्रणाली हम एक कस्टम बॉक्सिंग प्रकार है जो प्रणाली कैसे की प्रतिलिपि करने के लिए और इसे मुक्त बताया बन जाएगा के साथ हमारे कस्टम struct _PersonDetails
रजिस्टर करने के लिए। विवरण यहां हैं: Boxed Types
G_DEFINE_BOXED_TYPE (PersonDetails, person_details,
person_details_copy,
person_details_free)
. . .
static gpointer
person_details_copy (gpointer data)
{
struct _PersonDetails *details = (struct _PersonDetails *)data;
struct _PersonDetails *copy = g_new (struct _PersonDetails, 1);
// We need to copy the string
copy->name = g_strdup (details->name);
copy->age = details->age;
return (gpointer) copy;
}
static void
person_details_free (gpointer data)
{
struct _PersonDetails *details = (struct _PersonDetails *)data;
// name was allocated so it needs freed as well
g_free (details->name);
g_free (details);
}
अब हम इस विषय मैं अब तक पढ़ा के बारे में
pspec = g_param_spec_boxed ("details", "Details", "The person's details", person_details_get_type(), G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_DETAILS, pspec);
बेस्ट और सबसे स्पष्ट व्याख्या का उपयोग कर हमारे प्रकार रजिस्टर कर सकते हैं। +1 – drahnr
g_param_spec_gtype() कॉल इस मामले में गलत है: बॉक्स्ड प्रकार के लिए आप g_param_spec_boxed उपयोग करना चाहिए(); g_param_spec_gtype() वास्तविक जीटीपी मान को संग्रहीत करने वाले गुणों के लिए है। भी, एक बॉक्स्ड प्रकार आप G_DEFINE_BOXED_TYPE() मैक्रो, जो आप के लिए get_type() फ़ंक्शन उत्पन्न करता है का उपयोग करना चाहिए रजिस्टर करने के लिए। – ebassi
@ebassi ने _spec_boxed कॉल को ठीक किया। आपके उत्तर के लिए – iain