كيف يتم تنفيذ الإشارة والفتحات تحت الغطاء؟

StackOverflow https://stackoverflow.com/questions/1406940

  •  05-07-2019
  •  | 
  •  

سؤال

تم طرح هذا السؤال بالفعل في هذا المنتدى ولكني لا أفهم هذا المفهوم.

كنت أقرأ حولها ويبدو أنه يتم تنفيذ الإشارة والفتحات باستخدام مؤشرات الوظائف ، أي الإشارة هي وظيفة كبيرة واحدة تستدعي جميع الفتحات المتصلة (مؤشرات الوظائف). هل هذا صحيح؟ وما هو دور ملفات MOC التي تم إنشاؤها في القصة بأكملها؟ لا أفهم كيف تعرف وظيفة الإشارة الفتحات التي يجب استدعاءها ، أي الفتحات المتصلة بهذه الإشارة.

شكرا على وقتك

هل كانت مفيدة؟

المحلول

QT ينفذ هذه الأشياء بطريقة تشبه اللغات المفسرة. أي أنه يقوم بإنشاء جداول الرموز التي تعين أسماء الإشارة إلى مؤشرات الوظيفة ، والحفاظ عليها وتبحث عن مؤشر الوظيفة باسم الوظيفة عند الحاجة.

في كل مرة تنبعث منها إشارة ، أي الكتابة

emit something();

أنت في الواقع تسمي something() الوظيفة ، التي تم إنشاؤها تلقائيًا بواسطة برنامج التحويل البرمجي meta ووضعها في أ *.moc ملف. ضمن هذه الوظيفة ، يتم التحقق من الفتحات التي ترتبط بها هذه الإشارة في الوقت الحالي ، ويتم استدعاء وظائف الفتحة المناسبة (التي قمت بتطبيقها في مصادرك الخاصة) بالتتابع عبر جداول الرموز (بالطريقة الموضحة أعلاه). و emit, ، مثل الكلمات الرئيسية الأخرى الخاصة بـ QT ، يتم التخلص منها فقط بواسطة C ++ Preprocessor بعد *.moc تم إنشاؤها. في الواقع ، في أحد رؤوس كيو تي (QobjectDefs.h) ، توجد مثل هذه الخطوط:

#define slots 
#define signals protected
#define emit

وظيفة الاتصال (connect) فقط يعدل جداول الرموز التي يتم الحفاظ عليها في الداخل *.moc الملفات ، والوسائط التي تم نقلها إليها (مع SIGNAL() و `وحدات الماكرو) هي أيضا معالجة مسبقا لمطابقة الجداول.

هذه هي الفكرة العامة. في إجابة أخرى له ، ジョージ يزودنا بالروابط إلى قائمة المراسلة و ل آخر سؤال حول هذا الموضوع.

نصائح أخرى

أعتقد أنني يجب أن أضيف ما يلي.

هنالك سؤال آخر مرتبط -- وهناك مقال جيد جدا يمكن اعتبار ذلك بمثابة توسع مفصل تمامًا إجابه; هنا هذا المقال مرة أخرى, ، مع تحسن (على الرغم من أنه غير مثالي) بناء جملة رمز تمييز.

إليكم روايتي القصير ، قد يكون عرضة للأخطاء)

أساسا عندما نقدم Q_OBJECT الماكرو في تعريف الفئة لدينا ، يقوم المعالج المسبق بتوسيعه إلى ثابت QMetaObject إعلان مثال ، سيشاركه جميع الحالات من نفس الفصل:

class ClassName : public QObject // our class definition
{
    static const QMetaObject staticMetaObject; // <--= Q_OBJECT results to this

    // ... signal and slots definitions, other stuff ...

}

هذا المثال ، بدوره ، على التهيئة سوف تخزن التوقيعات ("methodname(argtype1,argtype2)") من الإشارات والفتحات ، ما الذي سيسمح بتنفيذ indexOfMethod() المكالمة ، التي تعود ، حسناً ، فهرس الطريقة من خلال سلسلة التوقيع:

struct Q_CORE_EXPORT QMetaObject
{    
    // ... skip ...
    int indexOfMethod(const char *method) const;
    // ... skip ...
    static void activate(QObject *sender, int signal_index, void **argv);
    // ... skip ...
    struct { // private data
        const QMetaObject *superdata; // links to the parent class, I guess
        const char *stringdata; // basically, "string1\0string2\0..." that contains signatures and other names 
        const uint *data; // the indices for the strings in stringdata and other stuff (e.g. flags)
        // skip
    } d;
};

الآن عندما moc يخلق moc_headername.cpp ملف لرأس فئة QT headername.h, ، يضع هناك سلاسل التوقيع والبيانات الأخرى الضرورية للتهيئة الصحيح لـ d الهيكل ، ثم يكتب رمز التهيئة ل staticMetaObject Singleton باستخدام هذه البيانات.

شيء مهم آخر يفعله هو توليد الكود للكائن qt_metacall() الطريقة ، يأخذ معرف طريقة الكائن ومجموعة من مؤشرات الوسيطة ويدعو الطريقة عبر فترة طويلة switch مثله:

int ClassName::qt_metacall(..., int _id, void **_args)
{
    // ... skip ...
    switch (_id) {
        case 0: signalOrSlotMethod1(_args[1], _args[2]); break; // for a method with two args
        case 1: signalOrSlotMethod2(_args[1]); break; // for a method with a single argument
        // ... etc ...
    }
    // ... skip ...
}

أخيرًا ، لكل إشارة moc يولد تطبيقًا يحتوي على ملف QMetaObject::activate() مكالمة :

void ClassName::signalName(argtype1 arg1, argtype2 arg2, /* ... */)
{
    void *_args[] = { 0, // this entry stands for the return value
                      &arg1, // actually, there's a (void*) type conversion
                      &arg2, // in the C++ style
                      // ...
                    };
    QMetaObject::activate( this, 
                           &staticMetaObject, 
                           0, /* this is the signal index in the qt_metacall() map, I suppose */ 
                           _args
                         );
}

وأخيرا، فإن connect() تقوم المكالمة بترجمة توقيعات طريقة السلسلة إلى معرفات عدد صحيح (تلك المستخدمة بواسطة qt_metacall()) ويحافظ على قائمة اتصالات الإشارة إلى الانحدار ؛ عندما تنبعث من الإشارة ، activate() يمر الرمز من خلال هذه القائمة ويستدعي "فتحات" الكائن المناسب عبر qt_metacall() طريقة.

لتلخيص ، الثابت QMetaObject يقوم المثيل بتخزين "المعلومات الوصفية" (سلاسل توقيع الأسلوب وما إلى ذلك) ، وهي تم إنشاؤها qt_metacall() توفر الطريقة "جدول طريقة" يتيح استدعاء أي إشارة/فتحة بواسطة فهرس ، وتطبيقات الإشارة التي تم إنشاؤها بواسطة moc استخدم هذه الفهارس عبر activate(), ، وأخيرا connect() هل مهمة الحفاظ على قائمة خرائط فهرس الإشارة إلى الانحدار.

*ملاحظة: هناك مضاعفات لهذا المخطط المستخدم للحالة عندما نريد تقديم إشارات بين خيوط مختلفة (أظن أن على المرء أن ينظر إلى blocking_activate() رمز) ، لكنني آمل أن تظل الفكرة العامة كما هي)

هذا هو فهمي القاسي للمقالة المرتبطة ، والتي قد تكون خاطئة بسهولة ، لذلك أوصي بالذهاب وقراءتها مباشرة)

ملاحظة. كما أرغب في تحسين فهمي لتنفيذ QT - يرجى إعلامي عن أي تناقضات في روحي!


منذ حذف إجابتي الأخرى (سابقًا) ليس تأسست في منشور بافيل شفيد ، وأشك في أن الشخص الذي حذف الجواب يهتم. )

pavel shvved:

أنا متأكد من أنه في مكان ما في رؤوس كيو تي هناك خط:

#define emit

فقط للتأكيد: العثور عليه في رمز QT القديم عن طريق البحث عن رمز Google. من المحتمل جدًا أنه لا يزال هناك) ؛ كان مسار الموقع الموجود:

ftp://ftp.slackware-brasil.com.br›Slackware-7.1› Contrib ›KDE-1.90› QT-2.1.1.TGZ ›usr› lib ›QT-2.1.1› src ›kernel›QobjectDefs.h


رابط تكميلي آخر: http://lists.trolltech.com/qt-interest/2007-05/thread00691-0.html - انظر الجواب من قبل أندرياس باكولات


وهنا قطعة أخرى من الجواب: سؤال QT: كيف تعمل الإشارات والفتحات؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top