C ++ ООП регистрация функции обратного вызова (проблема определения типа) - PullRequest
0 голосов
/ 30 января 2012

В основном я пытаюсь упаковать OpenNI Kinect в среду промежуточного программного обеспечения RT. OpenNI Kinect использует обратный вызов и должен быть зарегистрирован.

Чтобы сделать это, я мог бы объявить функции обратного вызова и соответствующие переменные в global без проблем.

// -----------------------------------------------
// 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
}

Это пример typedef параметра 1:

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

Моя платформа разработки - MS Visual Studio 2008. Будучи новичком, я не могу решить проблему. Надеюсь на любую помощь.

1 Ответ

4 голосов
/ 30 января 2012

Обратные вызовы должны быть указателями на функции. Вы пытаетесь использовать функции указателей на член. Они не одно и то же. (Из comp.lang.c ++ FAQ: Отличается ли тип «указатель на функцию-член» от «указатель на функцию»? ). Функции-члены должны работать с объектом этого класса.

Вы можете устранить ошибку компиляции, если вместо этого сделаете свои функции static методами класса.

Кстати, вы действительно мало что сделали, чтобы избежать использования глобальных переменных. Что - настоящая проблема; не имеет большого значения, находятся ли ваши функции обратного вызова в глобальной области или нет (тем более что вы можете поместить их в анонимное пространство имен или использовать ключевое слово static, чтобы ограничить их только модулем компиляции этого файла). Обратите внимание, что использование static переменных-членов на самом деле ничем не отличается от использования глобальных переменных.

Я не знаком с этим SDK, но вам, вероятно, следует упаковать любую необходимую информацию в struct или class и, вероятно, передать указатель на него через этот параметр void* pCookie.

...