コンパイル時に fatal error LNK1120 のエラーが発生してしまう


でんでん  2009-02-21 00:00:11  No: 69712

VC++6.0
Windows XP

プロジェクトをダイアログ形式で作成し、
コンパイルすると以下のエラーが発生します。
関数、変数等は正しく宣言されているかと思います。
何か原因の分かるようでしたら、ご教授願いたいと思います。
以下、エラー内容・ソースを記載します。
宜しくお願い致します。

-------------------------------------------------------
SetWinEventHookDemo2Dlg.obj : error LNK2001: 外部シンボル ""private: static void (__stdcall CSetWinEventHookDemo2Dlg::* CWinEvent<class CSetWinEventHookDemo2Dlg>::m_pfnCallback)(unsigned long,unsigned long,struct HWND__ *,long,long,unsigned long,unsign
ed long)" (?m_pfnCallback@?$CWinEvent@VCSetWinEventHookDemo2Dlg@@@@0P8CSetWinEventHookDemo2Dlg@@AGXKKPAUHWND__@@JJKK@ZQ2@)" は未解決です
SetWinEventHookDemo2Dlg.obj : error LNK2001: 外部シンボル ""private: static class CSetWinEventHookDemo2Dlg * CWinEvent<class CSetWinEventHookDemo2Dlg>::m_pT" (?m_pT@?$CWinEvent@VCSetWinEventHookDemo2Dlg@@@@0PAVCSetWinEventHookDemo2Dlg@@A)" は未解決です
Debug/SetWinEventHookDemo2.exe : fatal error LNK1120: 外部参照 2 が未解決です。

-----------------------------------------------------------
winevent.h

#include <winable.h>

template <typename T>
class CWinEvent 
{
public:
  typedef VOID ( CALLBACK T::*PFNCALLBACK )( HWINEVENTHOOK, DWORD, HWND, LONG, LONG, DWORD, DWORD );
  
  static HWINEVENTHOOK InstallWinEventHook( T * pT, 
                      PFNCALLBACK pfn, 
                      UINT eventMin, 
                      UINT eventMax, 
                      HMODULE hModWinEventProc, 
                      DWORD idProcess, 
                      DWORD idThread, 
                      UINT dwFlags );

private:
  static T * m_pT;
  static PFNCALLBACK m_pfnCallback;

private:
  CWinEvent( void ) {};
  ~CWinEvent( void ) {};

    static VOID CALLBACK WinEventProc( HWINEVENTHOOK hWinEventHook, 
                  DWORD event, 
                  HWND hwnd, 
                  LONG idObject, 
                  LONG idChild, 
                  DWORD dwEventThread, 
                  DWORD dwmsEventTime );
};

template <typename T>
HWINEVENTHOOK CWinEvent<T>::InstallWinEventHook( T * pT, 
                         PFNCALLBACK pfn, 
                         UINT eventMin, 
                         UINT eventMax, 
                         HMODULE hModWinEventProc, 
                         DWORD idProcess, 
                         DWORD idThread, 
                         UINT dwFlags )
{
  m_pT = pT;
  m_pfnCallback = pfn;

  return SetWinEventHook( eventMin, 
              eventMax, 
              hModWinEventProc, 
              WinEventProc, 
              idProcess, 
              idThread, 
              dwFlags );
}

template <typename T>
VOID CALLBACK CWinEvent<T>::WinEventProc( HWINEVENTHOOK hWinEventHook, 
                     DWORD event, 
                     HWND hwnd, 
                     LONG idObject, 
                     LONG idChild, 
                     DWORD dwEventThread, 
                     DWORD dwmsEventTime )
{
  ( m_pT->*m_pfnCallback )( hWinEventHook, 
              event, 
              hwnd, 
              idObject, 
              idChild, 
              dwEventThread, 
              dwmsEventTime );
}

----------------------------------------
SetWinEventHookDemo2Dlg.h

#include "winevent.h"

class CSetWinEventHookDemo2Dlg : public CDialog
{
// 構築
public:
  CSetWinEventHookDemo2Dlg(CWnd* pParent = NULL);  // 標準のコンストラクタ

// ダイアログ データ
  //{{AFX_DATA(CSetWinEventHookDemo2Dlg)
  enum { IDD = IDD_SETWINEVENTHOOKDEMO2_DIALOG };
    // メモ: この位置に ClassWizard によってデータ メンバが追加されます。
  //}}AFX_DATA

  // ClassWizard は仮想関数のオーバーライドを生成します。
  //{{AFX_VIRTUAL(CSetWinEventHookDemo2Dlg)
  protected:
  virtual void DoDataExchange(CDataExchange* pDX);  // DDX/DDV のサポート
  //}}AFX_VIRTUAL

// インプリメンテーション
private:
  VOID CALLBACK WinEventProc( HWINEVENTHOOK hWinEventHook, 
                DWORD event, 
                HWND hwnd, 
                LONG idObject, 
                LONG idChild, 
                DWORD dwEventThread, 
                DWORD dwmsEventTime );

protected:
  HICON m_hIcon;

  HWINEVENTHOOK  m_hWinEventHook;

  // 生成されたメッセージ マップ関数
  //{{AFX_MSG(CSetWinEventHookDemo2Dlg)
  virtual BOOL OnInitDialog();
  afx_msg void OnPaint();
  afx_msg HCURSOR OnQueryDragIcon();
  //}}AFX_MSG
  DECLARE_MESSAGE_MAP()
};

------------------------------------------------------------
SetWinEventHookDemo2Dlg.cpp

BOOL CSetWinEventHookDemo2Dlg::OnInitDialog()
{
  CDialog::OnInitDialog();

  // このダイアログ用のアイコンを設定します。フレームワークはアプリケーションのメイン
  // ウィンドウがダイアログでない時は自動的に設定しません。
  SetIcon(m_hIcon, TRUE);      // 大きいアイコンを設定
  SetIcon(m_hIcon, FALSE);    // 小さいアイコンを設定
  
  // 
  m_hWinEventHook = CWinEvent<CSetWinEventHookDemo2Dlg>::InstallWinEventHook( this, 
                              WinEventProc, 
                              EVENT_SYSTEM_FOREGROUND, 
                              EVENT_SYSTEM_FOREGROUND, 
                              NULL, 
                              0, 
                              0, 
                              WINEVENT_OUTOFCONTEXT );

  
  return TRUE;  // TRUE を返すとコントロールに設定したフォーカスは失われません。
}

VOID CALLBACK CSetWinEventHookDemo2Dlg::WinEventProc( HWINEVENTHOOK hWinEventHook, 
                DWORD event, 
                HWND hwnd, 
                LONG idObject, 
                LONG idChild, 
                DWORD dwEventThread, 
                DWORD dwmsEventTime )
{
  TRACE( _T( "コールバック" ) );
}


επιστημη  URL  2009-02-21 00:44:22  No: 69713

エラー・メッセージ"そのまんま"じゃないんですか?

m_pfnCallback と m_pT が未定義なんでしょうね。
確かにコード上には定義してるとこが見当たりませんね。


aetos  2009-02-21 00:49:18  No: 69714

もうちょい補足しますと、クラスの静的メンバ変数は「宣言」とは別に、クラス宣言の外に「定義」が必要です。

> private:
> static T * m_pT;
> static PFNCALLBACK m_pfnCallback;

こいつらは「宣言」です。

別に「定義」を用意するというのは、例えば、

class Hoge
{
  static int value; // これは宣言
};

int Hoge::value; // これが定義

みたいなのが必要ってことです。
テンプレートの場合、どこにどう書くかは、ちょいと頭をひねってみてください。


でんでん  2009-02-21 05:41:33  No: 69715

επιστημη様、aetos様ご回答ありがとうございます。
static変数の宣言が抜けていました。
ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加