C ++ OOP注册回调函数(typedef问题)

时间:2012-01-30 11:48:47

标签: c++ kinect openni

基本上我正在尝试将OpenNI Kinect打包到RT中间件框架中。 OpenNI Kinect使用回调并且必须注册。

为此,我可以在没有问题的情况下在全局声明回调函数和相关变量。

// -----------------------------------------------
// Global
// ----------------------------------------------
// Declare OpenNI nodes
xn::Context g_Context;
xn::ScriptNode g_scriptNode;
xn::DepthGenerator g_DepthGenerator;
xn::UserGenerator g_UserGenerator;
// ... more codes

// Define callback functions
// Callback: New user was detected
void User_NewUser(xn::UserGenerator& generator, XnUserID nId, void* pCookie)
{
    // ... some codes
    if (g_bNeedPose)
    {
        g_UserGenerator.GetPoseDetectionCap().StartPoseDetection(g_strPose, nId);
    }
    // ... some codes
}

// Callback: An existing user was lost
void User_LostUser(xn::UserGenerator& generator, XnUserID nId, void* pCookie)
{
    // ... some codes
}

// -----------------------------------------------
// Member
// ----------------------------------------------
// Register callback functioins in the RT-middleware class (OOP)
RTC::ReturnCode_t rtc_kinect::onActivated(RTC::UniqueId ec_id)
{
    // ... some codes
    nRetVal = g_UserGenerator.RegisterUserCallbacks(User_NewUser, User_LostUser, NULL, hUserCallbacks);
    // ... some codes
}

以上工作。但是,有人告诉我,使用全局变量和函数是不合适的。

我试图将回调函数和相关变量作为中间件类的成员移动,但是不成功。代码是:

// ----------------------------------------
// private members
// ----------------------------------------
// Declare OpenNI nodes as member variables
xn::Context g_Context;
xn::ScriptNode g_scriptNode;
xn::DepthGenerator g_DepthGenerator;
xn::UserGenerator g_UserGenerator;
// ... more codes

// Define callback functions as member function
// Callback: New user was detected
void XN_CALLBACK_TYPE rtc_kinect::User_NewUser(xn::UserGenerator& generator, XnUserID nId, void* pCookie)
{
    // ... some codes
    if (g_bNeedPose)
    {
        g_UserGenerator.GetPoseDetectionCap().StartPoseDetection(g_strPose, nId);
    }
    else
    {
        g_UserGenerator.GetSkeletonCap().RequestCalibration(nId, TRUE);
    }
}

// Callback: An existing user was lost
void XN_CALLBACK_TYPE rtc_kinect::User_LostUser(xn::UserGenerator& generator, XnUserID nId, void* pCookie)
{
    // ... some codes
}


// Register callback functioins in the RT-middleware class
RTC::ReturnCode_t rtc_kinect::onActivated(RTC::UniqueId ec_id)
{
    // ... some codes
    nRetVal = g_UserGenerator.RegisterUserCallbacks(&rtc_kinect::User_NewUser, &rtc_kinect::User_LostUser, NULL, hUserCallbacks);
    // ... some codes
}

编译器报告了以下错误:

error C2664: 'xn::UserGenerator::RegisterUserCallbacks' : cannot convert parameter 1 from 'void (__stdcall rtc_kinect::* )(xn::UserGenerator &,XnUserID,void *)' to 'xn::UserGenerator::UserHandler'
error C2664: 'xn::PoseDetectionCapability::RegisterToPoseDetected' : cannot convert parameter 1 from 'void (__stdcall rtc_kinect::* )(xn::PoseDetectionCapability &,const XnChar *,XnUserID,void *)' to 'xn::PoseDetectionCapability::PoseDetection'
.... and many more

这是回调注册函数定义的一个示例:

inline XnStatus RegisterUserCallbacks(UserHandler NewUserCB, UserHandler LostUserCB, void* pCookie, XnCallbackHandle& hCallback)
{
    // ... some codes
}

这是参数1的typedef的一个例子:

typedef void (XN_CALLBACK_TYPE* UserHandler)(UserGenerator& generator, XnUserID user, void* pCookie);

我的开发平台是MS Visual Studio 2008。 作为新手,我无法解决问题。希望得到任何帮助。

1 个答案:

答案 0 :(得分:4)

回调是指向函数的指针。您正在尝试使用指向成员函数的指针。他们不是一回事。 (来自comp.lang.c ++ FAQ:Is the type of "pointer-to-member-function" different from "pointer-to-function"?)。成员函数需要在该类的对象上运行。

如果您改为使用函数static类方法,则可以解决编译错误。

顺便说一下,你没有做太多工作来避免使用全局变量。 是真正的问题;您的回调函数是否在全局范围内并不重要(特别是因为您可以将它们放在匿名命名空间中或使用static关键字将它们限制为仅限于该文件的编译单元)。请注意,使用static成员变量与使用全局变量没有任何不同。

我不熟悉此SDK,但您可能应该将所需的任何信息打包到structclass中,并可能通过void* pCookie参数传递指向它的指针。