سؤال

 
io_iterator_t enumerator;
kern_return_t   result;
result = IOServiceAddMatchingNotification(
             mNotifyPort,
             kIOMatchedNotification,
             IOServiceMatching( "IOFireWireLocalNode" ),
             serviceMatchingCallback, 
             (void *)0x1234,
             & enumerator );

serviceMatchingCallback((void *)0x1234, enumerator);

إذا أعلنت ServiceMatchIncallback باعتبارها ثابتة ، فهي تعمل ، لكنني لا أريد أن تكون ثابتة. هل هناك طريقة لتمرير وظيفة رد الاتصال غير المنتظمة؟

شكرًا لك

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

المحلول

يمكنك الاحتفاظ بها ثابتة ، ولكن استخدم userdata لتخزين this مؤشر بالإضافة إلى أي مستخدم آخر تريده (عن طريق تعبئتها في بنية ، على سبيل المثال) ثم اتصل على رد اتصال خاص بكائن من الإصدار الثابت عن طريق الاتصال this->someCallback (أين this هو المؤشر المخزن في userdata ، بالطبع).

نصائح أخرى

النموذج الأولي ل ioservicematchingCallback غير متوافق مع طريقة فئة غير قاسية (ومن الناحية الفنية غير متوافق مع طريقة فئة ثابتة أيضًا) ، لذلك لن تكون قادرًا على استخدام ذلك.

لكن لحسن الحظ ioserviceaddmatchingnotification يدعم مؤشر السياق (أو كما يسمونه ، refcon) والذي سيسمح لك بإنشاء thunk لا يعتمد على البيانات العالمية.

تحتاج إلى تحديد رد اتصال مع ربط متوافق (أي Extern "C"). ستؤدي هذه الوظيفة إلى إلقاء refcon على مؤشر الكائن الخاص بك ثم إعادة توجيه المكالمة إلى طريقة المثيل الخاصة بك:

extern "C"
void io_callback(void *refcon, io_iterator_t iterator)
{
    myclass *c = static_cast<myclass *>(refcon);
    c->real_callback(iterator);
}

ثم ، عندما تتصل بـ iOServiceadDmatchingNotification ، تأكد من نقل مؤشر إلى كائنك لـ Refcon (هنا أفترض أنك تتصل بـ ioserviceaddmatchingnotification من وظيفة عضو ولديك هذا المؤشر):

result = IOServiceAddMatchingNotification(
             mNotifyPort,
             kIOMatchedNotification,
             IOServiceMatching( "IOFireWireLocalNode" ),
             serviceMatchingCallback, 
             this,
             &enumerator );

لا مباشرة.

يحتوي مؤشر الوظيفة غير الاستاتيكي (المعروف باسم مؤشر دالة الأعضاء) على معلمة مخفية "حتى لا تتطابق الأنواع. الوظيفة الثابتة لا تحتوي على مؤشر "هذا.

للتغلب على هذا ، يجب أن تكون قادرًا على تمرير عنصر بيانات المستخدم وهو مؤشر "هذا" للكائن الذي تريد استخدامه كرد اتصال. بعد ذلك ، حدد عضوًا ثابتًا يتم تمرير بيانات المستخدم ، ويحولها إلى مؤشر إلى كائن الفئة واتصل العضو غير القديم عليه.

بالنظر إلى الكود الذي نشرته ، من الصعب معرفة ما إذا كان هناك كائن بيانات مستخدم ، وربما الأخير ولكن = معلمة واحدة.

لا ، يتوقع أحد الأعضاء غير القتلي كائنًا ، ولم يكن لدى المتصل (مكالمات المكالمات) ولن يوفره.

لا. الأساليب غير القتالية تحتاج إلى كائن للعمل عليه. إذا كنت تريد فقط تمرير الطريقة التي ستحتاج إليها أيضًا بطريقة ما لإخبار الوظيفة التي يمكنها استدعاء الطريقة.

أstatic الوظيفة لها ضمنية this المعلمة ، وبالتالي سيكون لها توقيع خاطئ لرد الاتصال.

آسف ، لا توجد طريقة سهلة لتجنب جزيرة القفز.

إذا وضعت هذا السطر في مُنشئك (أو في أي طريقة مثيل) ، فيجب أن تكون قادرًا على القيام بذلك.

تعديللقد لاحظت للتو أنك تستخدم API Space Iokit ، وليس جانب Kext ، مما يجعل هذا المنشور غير ذي صلة.


على افتراض أنك تعمل في OS X kernel ، يمكنك فعل ذلك بالفعل. يمكنك استعمال ال OSMemberFunctionCast Macro لتحويل مؤشر وظيفة العضو إلى مؤشر دالة C العادي ، لاحظ أنه ينبغي استدعاؤه مع الوسيطة الأولى تشير إلى مثيل للفصل ، على سبيل المثال.

IOServiceMatchingCallback mycb = OSMemberFunctionCast(IOServiceMatchingCallback,
    &myclassinstance, &MyClass::cb_method);

result = IOServiceAddMatchingNotification(
             mNotifyPort,
             kIOMatchedNotification,
             IOServiceMatching( "IOFireWireLocalNode" ),
             mycb,
             &myclassinstance,
             &enumerator);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top