سؤال

وأولا وقبل كل شيء يجب أن أعترف أن مهارات البرمجة بلدي محدودة جدا وأخذت أكثر من (صغير حقا) C الموجودة OOP مشروع ++ حيث كنت في محاولة لدفع أشيائي الخاصة في ولسوء الحظ أنا تواجه مشكلة التي تتجاوز معرفتي وآمل أن تجد بعض المساعدة هنا. أنا أعمل مع مكتبة طرف ثالث (والتي لا يمكن تغييرها) لاقتناص الصور من الكاميرا وسوف تستخدم بعض الأسماء نائبا هنا.

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

ThirdPartyGrab (HookFunction);

و"HookFunction" يجب أن يعلن على النحو التالي:

long _stdcall HookFunction (long, long, void*);

وأو "BUF_HOOK_FUNCTION_PTR" الذي أعلن أنه

typedef long (_stdcall *HOOK_FUNCTION_PTR) (long, long, void*);

والآن لدي تطبيق C ++ وفئة "MyFrameGrabber" التي يجب أن تغلف كل شيء أقوم به. لذلك أنا وضعت في وظيفة هوك كعضو الخاص مثل هذا:

long _stdcall HookFunction (long, long, void*);

وأيضا هناك جمهور وظيفة الفراغ "StartGrab" في صفي الذي يجب أن يبدأ الاستيلاء. داخل أحاول الاتصال على:

ThirdPartyGrab (..., HookFunction, ...);

والذي (ليس من المستغرب) فشل. وتقول أن استدعاء دالة لMyFrameGrabber :: HookFunction يفتقد قائمة الوسائط وأود أن محاولة استخدام وMyFrameGrabber :: HookFunction لإنشاء مؤشر بدلا من ذلك. ومع ذلك يمر "وMyFrameGrabber :: HookFunction" بدلا يؤدي إلى خطأ آخر أن هذا لا يمكن أن يتم تحويلها إلى BUF_HOOK_FUNCTION_PTR.

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

وتحرير 14.01.08: أنا جربت الحل المفرد منذ أن كنت لا تستطيع تغيير مكتبة طرف ثالث، ومؤشر باطل هو فقط للبيانات التي يتم استخدامها داخل دالة ربط. ومما يؤسف له أنه لم يعمل من خارج منطقة الجزاء كما كنت آمل .... أنا لا أعرف إذا كانت وظيفة ثابتة يجب أن يكون في فئة منفصلة حتى وضعه في صفي "MyFrameGrabber":

static MyFrameGrabber& instance()
{
        static MyFrameGrabber _instance;
        return _instance;
}
long Hook(long, long, void*); // Implementation is in a separate cpp file

في ملف حزب الشعب الكمبودي لي ولدي وظيفة call_hook:

long MFTYPE call_hook(long x, MIL_ID y, void MPTYPE *z)
{
    return MyFrameGrabber::instance().Hook(x,y,z);
}
void
MyFrameGrabber::grab ()
{
    ThirdPartyGrab(..., call_hook, ...);
}

ولكن هذا يعطيني خطأ في static MatroxFrameGrabber _instance; أن يتم العثور على أي منشئ معيار المطابقة. هذا صحيح لأن بلدي MyFrameGrabber منشئ يبدو مثل هذا:

MyFrameGrabber (void* x,
                const std::string &y, int z,
                std::string &zz);

وحاولت أن تضع في MyFrameGrabber(); منشئ فارغة ولكن هذا يؤدي إلى خطأ رابط. يجب أن تمرير المعلمات فارغة إلى منشئ MyFrameGrabber في المفرد؟ أو هل أنا بحاجة إلى الدرجة هوك منفصلة وإذا كانت الإجابة بنعم فكيف يمكنني الوصول إلى وظائف MyFrameGrabber؟ شكرا لك مقدما.

والثانية تحرير 15.01.08: I تطبيق التغييرات ويجمع وصلات الآن. للأسف لا أستطيع أن اختبار هذا في وقت التشغيل بعد لانها DLL وليس لدي أي تصحيح المتصل إكس بعد، وهناك مشاكل أخرى أثناء التهيئة الخ I سيمثل منصب الجواب لأنني متأكد من أن هذا هو الطريق الصحيح للقيام بذلك.

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

المحلول

والسبب "وMyFrameGrabber :: HookFunction" لا يمكن تحويلها إلى BUF_HOOK_FUNCTION_PTR هو أنه، كونه عضوا في الطبقة، فقد ضمنا كما المعلمة الأولى في "هذا" المؤشر، وبالتالي لا يمكنك تحويل وظيفة عضو إلى عدم الدالة العضو: تواقيع اثنين من نظرة واحدة ولكن تختلف في الواقع

.

وأود أن أعلن واجهة، وتحديد وظيفة للدعوة، يكون صفك تنفيذ ذلك وتمرير الكائن نفسه بدلا من الاستدعاء (يمكنك التفكير في واجهة كبديل وجوه المنحى من مؤشر دالة):

class IHookInterface{
public:
    virtual long HookFunction(long, long, void*) = 0;
};
 class HookClass : public IHookInterface{
public:
    virtual long Hook(long, long, void*) {
        // your code here... 
    }
};

و// تعريف جديد: ThirdPartyGrab (...، IHookInterface، ...)؛

.

وتحرير - حل آخر ممكن في حال لم تتمكن من تعديل المكتبة: استخدام المفرد بدلا من وظيفة ثابتة

class HookClass{
public:
    static HookClass& instance(){
        static HookClass _instance;
        return _instance;
    }
    long Hook(long, long, void*) {
        // your code here... 
    }
};

long call_hook(long x,long y,void * z){
    return HookClass::instance().Hook(x,y,z);
}

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

class HookClass{
public:

    HookClass(string x,string y...){
    }

    long Hook(long, long, void*) {
        // your code here... 
    }
};

static HookClass * hook_instance = 0;

long call_hook(long x,long y,void * z){
    if (0 != hook_instance){
        return hook_instance->Hook(x,y,z);
    }
}

int main(){
    hook_instance = new HookClass("x","y");
    ThirdPartyGrab(..., call_hook, ...);
}

نصائح أخرى

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

وتحتاج إلى كتابة دالة عضو ثابت، والتي يمكن أن تنتقل بوصفها وظيفة الاستدعاء إلى المكتبة. الوسيطة الأخيرة إلى HookFunction، وvoid*، تبدو لي كثيرا مثل الكعكة، حيث يمكن للمرء أن يمر منها المؤشر الخاص في.

وهكذا، وبشكل عام، ينبغي أن يكون شيء من هذا القبيل:

class MyClass {
  long MyCallback(long, long) {
    // implement your callback code here
  }

  static long __stdcall ThirdPartyGrabCallback(long a, long b, void* self) {
    return reinterpret_cast<MyClass*>(self)->MyCallback(a, b);
  }
public:
  void StartGrab() {
    ThirdPartyGrab(..., &MyClass::ThirdPartyGrabCallback, ..., this, ...);
  }
};

وهذا بالطبع لا تعمل إلا إذا كانت الوسيطة void* يفعل ما قلته. موقف this في الدعوة ThirdPartyGrab() يجب أن يكون من السهل العثور عند وجود توقيع وظيفة كاملة بما في ذلك أسماء المعلمات المتاحة.

scroll top