none
ジョイスティックを初期化したいのですが。Callback関数に引数を与える方法が? RRS feed

  • 質問

  • マウスに続いてジョイスティックを初期化したいのですが。

    クラス内での定義です:

    class SysImplement

    {

    public:
     LPDIRECTINPUT8         lpdi;
     LPDIRECTINPUTDEVICE8   m_mouse;
     LPDIRECTINPUTDEVICE8   m_joy;
     DIMOUSESTATE           mouse_state;

    BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE*    

                                           pdidInstance, VOID* pContext);

    ・・・

     

    初期化の関数内ではまず以下のことをしてマウス入力を成功させました:

     if (FAILED(DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&lpdi, NULL)))
      exit(1);
     if (FAILED(lpdi->CreateDevice(GUID_SysMouse, &m_mouse, NULL)))
      exit(1);
     if (FAILED(m_mouse->SetCooperativeLevel(hWnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE)))
      exit(1);
     if (FAILED(m_mouse->SetDataFormat(&c_dfDIMouse)))
      exit(1);
     if (FAILED(m_mouse->Acquire()))
      exit(1);

     

    //この次の行からジョイスティックに取り掛かりたいわけですが。このTutorialに沿って進んでいます。

    //http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/directx9_c/directx/input/tuts/tut3/step1enumeratingjoysticks.asp

     

     lpdi->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback,
                         NULL, DIEDFL_ATTACHEDONLY);

     

    しかし、以下のようなエラーが返されます:

    コンパイルしています...
    SysImplement.cpp
    C:\Program Files\Microsoft DirectX SDK (June 2006)\Include\dinput.h: DIRECTINPUT_VERSION undefined. Defaulting to version 0x0800
    .\src\SysImplement.cpp(24) : error C3867: 'SysImplement::EnumJoysticksCallback':
    関数呼び出しには引数リストがありません。メンバへのポインタを作成するために '&SysImplement::EnumJoysticksCallback' を使用してください

     

     “&”をつけてもエラーが返ってきます。

     

     lpdi->EnumDevices(DI8DEVCLASS_GAMECTRL, &EnumJoysticksCallback,
                         NULL, DIEDFL_ATTACHEDONLY);

    以下のようなエラーが返されます:

    .\src\SysImplement.cpp(24) : error C2276: '&' : 仮想関数のアドレスを取ろうとしました。

     

    私はCallback関数に引数を与える方法を理解していないのでしょうか?

    どなたかご教授をお願いします。あらかじめありがとうございます!

     

     

    2007年1月5日 7:31

回答

  • これは C++ の問題です。

    Tutorial では、C 関数として EnumJoysticksCallback が宣言されていたことと思いますが、ここでは class SysImplement のメンバ関数として宣言されています。

    このメンバ関数(非static)が実際に何に対応するのかは、実行時に決定されるためコンパイラには分かりません。結果、error C2276 が発生してしまうわけです。

    # 識者に尋ねるか…ないし、きちんとした文献を読んで正確なところを理解されることをお勧めします。

    で、どう対応するべきかについては、

    • class SysImplement の static メンバ関数として EnumJoysticksCallback を宣言する。
    • C関数として宣言する。

    のどちらかを選ぶことが多い…のだと思います(他に何か手段があるかもしれないですが…)。いずれの場合も、this ポインタが利用できませんから、「VOID* pContext」に SysImplement のインスタンスを渡すことになります。

    前者の例でしたら…

    class SysImplement

    {

    public:
     LPDIRECTINPUT8         lpdi;
     LPDIRECTINPUTDEVICE8   m_mouse;
     LPDIRECTINPUTDEVICE8   m_joy;
     DIMOUSESTATE           mouse_state;

     

     static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE*    

                                           pdidInstance, VOID* pContext);

    のように宣言して、初期化処理の EnumDevices の部分は下のようにいじります。

     lpdi->EnumDevices(DI8DEVCLASS_GAMECTRL, SysImplement::EnumJoysticksCallback,
                         this, DIEDFL_ATTACHEDONLY);

    それから、SysImplement ::EnumJoysticksCallback では、

    BOOL CALLBACK SysImplement::EnumJoysticksCallback(const DIDEVICEINSTANCE*    

                                           pdidInstance, VOID* pContext)

    {

       SysImplement* pThis = reinterpret_cast<SysImplement*> (pContext) ;

       //... 何か処理

    }

    という感じになるのでしょうか。

     

     

     

     

     

    2007年1月5日 11:24

すべての返信

  • これは C++ の問題です。

    Tutorial では、C 関数として EnumJoysticksCallback が宣言されていたことと思いますが、ここでは class SysImplement のメンバ関数として宣言されています。

    このメンバ関数(非static)が実際に何に対応するのかは、実行時に決定されるためコンパイラには分かりません。結果、error C2276 が発生してしまうわけです。

    # 識者に尋ねるか…ないし、きちんとした文献を読んで正確なところを理解されることをお勧めします。

    で、どう対応するべきかについては、

    • class SysImplement の static メンバ関数として EnumJoysticksCallback を宣言する。
    • C関数として宣言する。

    のどちらかを選ぶことが多い…のだと思います(他に何か手段があるかもしれないですが…)。いずれの場合も、this ポインタが利用できませんから、「VOID* pContext」に SysImplement のインスタンスを渡すことになります。

    前者の例でしたら…

    class SysImplement

    {

    public:
     LPDIRECTINPUT8         lpdi;
     LPDIRECTINPUTDEVICE8   m_mouse;
     LPDIRECTINPUTDEVICE8   m_joy;
     DIMOUSESTATE           mouse_state;

     

     static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE*    

                                           pdidInstance, VOID* pContext);

    のように宣言して、初期化処理の EnumDevices の部分は下のようにいじります。

     lpdi->EnumDevices(DI8DEVCLASS_GAMECTRL, SysImplement::EnumJoysticksCallback,
                         this, DIEDFL_ATTACHEDONLY);

    それから、SysImplement ::EnumJoysticksCallback では、

    BOOL CALLBACK SysImplement::EnumJoysticksCallback(const DIDEVICEINSTANCE*    

                                           pdidInstance, VOID* pContext)

    {

       SysImplement* pThis = reinterpret_cast<SysImplement*> (pContext) ;

       //... 何か処理

    }

    という感じになるのでしょうか。

     

     

     

     

     

    2007年1月5日 11:24
  • 問題は解決しました。

    Takashi SAKAMOTOさん、ありがとうございました!

    2007年1月5日 11:57