函数指向类成员函数的问题 [英] Function pointer to class member function problems

查看:155
本文介绍了函数指向类成员函数的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我必须承认我的编程技能相当有限,我接管了一个(真的很小)现有的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,应该启动Grab。里面我试着调用:

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

(毫不奇怪)。它说,对MyFrameGrabber :: HookFunction的函数调用错过参数列表,我应该尝试使用& MyFrameGrabber :: HookFunction来创建一个指针。但是传递& MyFrameGrabber :: HookFunction而导致另一个错误,这不能被转换为BUF_HOOK_FUNCTION_PTR。



阅读完整的 C ++ FAQ函数指针我认为我理解问题,但不能组成一个解决方案。我试图使挂钩函数静态,但这也导致转换错误。我也想到把钩子函数放在类之外,但我需要在钩子函数里面使用类函数。有另一种方式,还是我需要改变我的整个概念?



EDIT 14.01.08:
我测试了单例解决方法,因为我不能更改第三方库,void指针只用于挂钩功能。不幸的是,它没有成功的框,我希望....我不知道静态函数需要在一个单独的类,所以我把它放在我的MyFrameGrabber类:

  static MyFrameGrabber& instance()
{
static MyFrameGrabber _instance;
return _instance;
}
long Hook(long,long,void *); //实现是在单独的cpp文件



在我的cpp文件中我有call_hook函数: p>

  long MFTYPE call_hook(long x,MIL_ID y,void MPTYPE * z)
{
return MyFrameGrabber :: 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构造函数在单例吗?或者我需要有一个单独的Hook类,如果是的我如何访问MyFrameGrabber函数?提前致谢。



第二编辑15.01.08:
我应用了更改,现在编译和链接。不幸的是,我不能在运行时测试这个,因为它是一个DLL,我没有调试调用程序Exe,而且在初始化期间还有其他问题等。我将标记为答案的答案,因为我确信这是正确的方法做到这一点。

解决方案

无法将& MyFrameGrabber :: HookFunction转换为BUF_HOOK_FUNCTION_PTR的原因是, ,它隐含地作为第一个参数this指针,因此你不能将成员函数转换为非成员函数:两个签名看起来一样,但实际上是不同的。

我将声明一个接口,定义要调用的函数,让你的类实现它,并传递对象本身而不是回调(你可以认为接口是面向对象的函数指针替换):



  class IHookInterface {
public:
virtual long HookFunction(long,long,void *)= 0;
};
class HookClass:public IHookInterface {
public:
virtual long Hook(long,long,void *){
//你的代码在这里...
} b $ b};

// new definition:
ThirdPartyGrab(...,IHookInterface,...) ;



EDIT - 其他可能的解决方案,以防您无法修改库:使用单一而不是静态函数。

 类HookClass {
public:
static HookClass& instance(){
static HookClass _instance;
return _instance;
}
long Hook(long,long,void *){
//你的代码在这里...
}
};

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

第二编辑:您可以使用初始化方法稍微修改singleton类,该构造函数具有适当的参数,但也许它不如下面的解决方案更优雅,这是更简单的:

  class HookClass { 
public:

HookClass(s​​tring x,string y ...){
}

long Hook(long,long,void *){
//你的代码在这里...
}
};

static HookClass * hook_instance = 0;

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

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


First of all I have to admit that my programming skills are pretty limited and I took over a (really small) existing C++ OOP project where I try to push my own stuff in. Unfortunately I'm experiencing a problem which goes beyond my knowledge and I hope to find some help here. I'm working with a third party library (which cannot be changed) for grabbing images from a camera and will use some placeholder names here.

The third party library has a function "ThirdPartyGrab" to start a continuous live grab and takes a pointer to a function which will be called every time a new frame arrives. So in a normal C application it goes like this:

ThirdPartyGrab (HookFunction);

"HookFunction" needs to be declared as:

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

or "BUF_HOOK_FUNCTION_PTR" which is declared as

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

Now I have a C++ application and a class "MyFrameGrabber" which should encapsulate everything I do. So I put in the hook function as a private member like this:

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

Also there is a public void function "StartGrab" in my class which should start the Grab. Inside I try to call:

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

which (not surprisingly) fails. It says that the function call to MyFrameGrabber::HookFunction misses the argument list and I should try to use &MyFrameGrabber::HookFunction to create a pointer instead. However passing "&MyFrameGrabber::HookFunction" instead results in another error that this cannot be converted to BUF_HOOK_FUNCTION_PTR.

After reading through the C++ FAQ function pointers I think I understand the problem but can't make up a solution. I tried to make the hook function static but this also results in a conversion error. I also thought of putting the hook function outside of the class but I need to use class functions inside the hook function. Is there another way or do I need to change my whole concept?

EDIT 14.01.08: I tested the singleton workaround since I cannot change the third party library and the void pointer is only for data that is used inside the hook function. Unfortunately it didn't worked out of the box like I hoped.... I don't know if the static function needs to be in a separate class so I put it in my "MyFrameGrabber" class:

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

In my cpp file I have the call_hook function:

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, ...);
}

But this gives me an error in static MatroxFrameGrabber _instance; that no matching standard constructor is found. That's correct because my MyFrameGrabber constructor looks like this:

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

I tried to put in an empty constructor MyFrameGrabber(); but this results in a linker error. Should I pass empty parameters to the MyFrameGrabber constructor in the singleton? Or do I need to have a separate Hook Class and if yes how could I access MyFrameGrabber functions? Thanks in advance.

SECOND EDIT 15.01.08: I applied the changes and it compiles and links now. Unfortunately I cannot test this at runtime yet because it's a DLL and I have no Debug Caller Exe yet and there are other problems during initialization etc. I will mark the post as answer because I'm sure this is the right way to do this.

解决方案

The reason "&MyFrameGrabber::HookFunction" cannot be converted to a BUF_HOOK_FUNCTION_PTR is that, being a member of the class, it has implicitly as first parameter the "this" pointer, thus you cannot convert a member function to a non-member function: the two signatures look the same but are actually different.

I would declare an interface, defining the function to call, have your class implement it and pass the object itself instead of the callback (you can think of an interface as the object-oriented replacement of a function pointer):

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

// new definition: ThirdPartyGrab (..., IHookInterface, ...);

EDIT - other possible solution in case you cannot modify the library: use a singleton rather than a static function.

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);
}

SECOND EDIT: you might slightly modify the singleton class with an initialization method to call the constructor with the proper parameters, but maybe it is not more elegant than the following solution, which is simpler:

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, ...);
}

这篇关于函数指向类成员函数的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆