2013-02-12 6 views
6

GObject लाइब्रेरी वास्तव में बहुत ही दस्तावेज़ीकृत है। बनाई गई संस्थाओं के उद्देश्यों को समझना मुश्किल है। अर्थात्, मुझे GValue, GTypeValueTable, GTypeInfo, GParamSpec और TypeData की भूमिकाएं नहीं मिलती हैं।GValue का उद्देश्य, GTypeValueTable, GTypeInfo और GParamSpec

संक्षेप में, प्रकार पंजीकरण की प्रक्रिया निम्नानुसार है। प्रत्येक प्रकार को TypeNode संरचना द्वारा दर्शाया जाता है। TypeNode संरचनाओं के 2 स्टोरेज हैं: static_fundamental_type_nodes array स्थिर मौलिक प्रकारों के TypeNodes और स्थिर गैर-मौलिक प्रकारों के लिए static_type_nodes_ht हैश तालिका संग्रहीत करने के लिए। प्रत्येक GType मौलिक प्रकारों के मामले में static_fundamental_type_nodes में TypeNode के गैर-मौलिक प्रकार या अनुक्रमणिका के मामले में संबंधित TypeNode का स्मृति पता है। गतिशील प्रकारों का क्या होता है - मुझे नहीं पता, कृपया मुझे बताएं कि क्या आप कर सकते हैं। संबंधित कोड gtype_init फ़ंक्शन में रहता है, जो टाइप सिस्टम के प्रारंभ के लिए ज़िम्मेदार है: http://git.gnome.org/browse/glib/tree/gobject/gtype.c#n4323

enter image description here

GValue, GParamSpec और GObjectGTypes खुद को है, इसलिए वे प्रकार के रूप में पंजीकृत हैं।

GValue इसका उपयोग नए प्रकार के मानों को पंजीकृत करने के लिए किया जाता है, लेकिन कैसे?

GParameters और GParamSpecGObject प्रकार (यकीन नहीं) के पंजीकरण के लिए आवश्यक हो लगते हैं। यह वास्तव में कैसे किया जाता है? प्रत्येक की भूमिका क्या हैं?

सबसे महत्वपूर्ण रूप से: GTypeValueTable, GTypeInfo और TypeData की भूमिका क्या हैं? TypeData को TypeNode द्वारा संदर्भित किया गया है और इसमें GTypeValueTable और साथ ही साथ बॉक्सक्टेड डेटा, क्लासडाटा, आईफ़ेसडाटा, इंस्टेंसडेटा (क्यों इंस्टेंस, हम टाइपिंग नहीं कर रहे हैं?) शामिल हैं। इसके अलावा, वे एक दूसरे को डुप्लिकेट करते हैं, क्योंकि उनमें से सभी को base_init/finalize के संदर्भ शामिल हैं, class_init/finalize के पास GTypeValueTable का संदर्भ है।

तो, गोब्जेक्ट पाप, अगर आप इसे पढ़ रहे हैं, तो कृपया स्वयं को समझाएं! आपके द्वारा उपयोग की जाने वाली संरचनाओं के उद्देश्य का वर्णन करें।

उत्तर

14

इन कि तुम सच में जब तक आप कुछ बहुत ही निम्न स्तर कोड पर काम करने की कोशिश कर रहे हैं के बारे में परवाह करने की जरूरत के केवल दो 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); 
+0

बेस्ट और सबसे स्पष्ट व्याख्या का उपयोग कर हमारे प्रकार रजिस्टर कर सकते हैं। +1 – drahnr

+0

g_param_spec_gtype() कॉल इस मामले में गलत है: बॉक्स्ड प्रकार के लिए आप g_param_spec_boxed उपयोग करना चाहिए(); g_param_spec_gtype() वास्तविक जीटीपी मान को संग्रहीत करने वाले गुणों के लिए है। भी, एक बॉक्स्ड प्रकार आप G_DEFINE_BOXED_TYPE() मैक्रो, जो आप के लिए get_type() फ़ंक्शन उत्पन्न करता है का उपयोग करना चाहिए रजिस्टर करने के लिए। – ebassi

+0

@ebassi ने _spec_boxed कॉल को ठीक किया। आपके उत्तर के लिए – iain

संबंधित मुद्दे