お世話になります。
ビルドエラーの対応方法についてご指導を宜しくお願い致します。
●Windows XP VC++6 MFC ダイアログベース
●エラー内容
error LNK2001: 外部シンボル "_xGetSystemMetrics@4" は未解決です
error LNK2001: 外部シンボル "_xGetMonitorInfo@8" は未解決です
error LNK2001: 外部シンボル "_xMonitorFromPoint@12" は未解決です
fatal error LNK1120: 外部参照 3 が未解決です。
link.exe の実行エラー
●以下の文法を追加で発生しました。
※テストとして別プロジェクトで実行時は、問題ありませんでした。
//Append Start
#include <multimon.h>
#define COMPILE_MULTIMON_STUBS
//Append End
BOOL CDIDSDlg::OnInitDialog()
{
// Append Start
BOOL blRet = SetDidsDlg();
// Append End
}
BOOL CDIDSDlg::SetDidsDlg()
{
// Append Start
CRect crectDialog;
RECT rectDesktop;
HMONITOR MonitorHandle;
MONITORINFO MonitorInfo;
// ダイアログサイズ
GetWindowRect(&crectDialog);
// 画面(プライマリ)サイズ:画面下タスクバーを除いたサイズ
SystemParametersInfo(SPI_GETWORKAREA, 0, &rectDesktop, 0);
// 画面(セカンダリ)サイズ
POINT Point = {(long)rectDesktop.right, (long)rectDesktop.top};
MonitorHandle = ::MonitorFromPoint(Point, MONITOR_DEFAULTTOPRIMARY);
MonitorInfo.cbSize = sizeof(MonitorInfo);
::GetMonitorInfo(MonitorHandle, &MonitorInfo);
// ダイアログの表示位置
SetWindowPos(&wndTop, MonitorInfo.rcWork.left, MonitorInfo.rcWork.top, MonitorInfo.rcWork.right - MonitorInfo.rcWork.left, MonitorInfo.rcWork.bottom, SWP_SHOWWINDOW);
//Append END
return(TRUE);
}
実行はしていませんが、
#include <multimon.h>
より、
#define COMPILE_MULTIMON_STUBS
が先なのではないでしょうか?
multimon.h
の最初に以下の文が書いてありますし、
// Exactly one source must include this with COMPILE_MULTIMON_STUBS defined.
146行目に
#ifdef COMPILE_MULTIMON_STUBS
があるので、インクルード前に定義しないとだめっぽいですね。
書き込みありがとうございます。
以下に変更して見ました。
<変更>
#define COMPILE_MULTIMON_STUBS
#include <multimon.h>
<結果>
error LNK2005: _InitMultipleMonitorStubs はすでに xx.obj で定義されています
error LNK2005: _xGetSystemMetrics@4 はすでに xx.obj で定義されています
fatal error LNK1169: 1 つ以上の複数回定義されているシンボルが見つかりました
link.exe の実行エラー
<その他>
この2行の定義の仕方に問題ありかなと思ってきました。
でも、調べ方がわかりません。
#define COMPILE_MULTIMON_STUBS
#include <multimon.h>
> ※テストとして別プロジェクトで実行時は、問題ありませんでした。
この時とインクルードする順番やインクルードしているファイルは
同じですか?
>この時とインクルードする順番やインクルードしているファイルは同じですか?
インクルードした順番
・テスト時は以下の順番です。
#define COMPILE_MULTIMON_STUBS
#include <multimon.h>
インクルードしているファイル
・本番用ではStdafx.hに以下が追加されています。
#include <afxsock.h>
#include <math.h>
・カメラを使用しているので、提供されたヘッダーファイルを
使用しています。
情報不足の場合、ご指摘をお願いします。
以下の2行のみを、Stdafx.h, DIDS.h, DIDSDlg.cpp, DIDSDlg.hの
何れかに追加してリビルドしてもLNK2005が出ました。
#define COMPILE_MULTIMON_STUBS
#include <multimon.h>
複数回定義されている
と、あるので<multimon.h>が二回以上呼ばれているのではないでしょうか?
C/C++ は同じヘッダーを複数回読んだときの対策を自分で行わないといけません。
今後のレベルアップのために、
#ifdef #pragma once
などを調べてみてはいかがでしょうか?
(multimon.h 自身になぜ対策が施されていないかは疑問ですが)
> 今後のレベルアップのために、
> #ifdef #pragma once
> などを調べてみてはいかがでしょうか?
> (multimon.h 自身になぜ対策が施されていないかは疑問ですが)
これらによる複数回取り込み対策は、ひとつの翻訳単位に複数回同じヘッダの内容を
取り込まないようにするものです。
今回の問題は、複数の翻訳単位がCOMPILE_MULTIMON_STUBS付きでmultimon.hを取り
込むことにより、COMPILE_MULTIMON_STUBS が定義されている時にその定義が展開される
xGetSystemMetrics() などの関数を何度もコンパイルしてしまうことですのであまり
関係がありません。
ちなみに、試してはいませんが、ソースを読む限り、multimon.hは一翻訳単位内での
複数回取り込みの対策はしっかり行っているようです。
さて、ポン太さんが以前に引用されたmultimon.h内の記述
>> // Exactly one source must include this with COMPILE_MULTIMON_STUBS defined.
を見直してみましょう。
アプリケーション全体で *ひとつのソースだけ* がCOMPILE_MULTIMON_STUBS付きで
multimon.hを取り込むべし、とあります。
つまり、その他のソースでは、COMPILE_MULTIMON_STUBSを付けてはならないわけです。
COMPILE_MULTIMON_STUBS を付けてmultimon.hを取りこむソースとしては、
Stdafx.cpp (Stdafx.hではない) あたりが妥当ではないでしょうか。
#define COMPILE_MULTIMON_STUBS
#include <multimon.h>
をStdafx.cppに追加してみました
// stdafx.cpp : 標準インクルードファイルを含むソース ファイル
// DIDS.pch : 生成されるプリコンパイル済ヘッダー
// stdafx.obj : 生成されるプリコンパイル済タイプ情報
#include "stdafx.h"
// add start
#define COMPILE_MULTIMON_STUBS
#include <multimon.h>
// add end
リビルド後、以下のエラーが発生しました。
error C2065: 'HMONITOR' : 定義されていない識別子です。
error C2065: 'MONITORINFO' : 定義されていない識別子です。
multimon.hに以下の記載がありますが、関係ありかな???
// HMONITOR is already declared if _WIN32_WINNT >= 0x0500 in windef.h
// This is for components built with an older version number.
以下は、上記を翻訳
HMONITORは_WIN32_WINNT>windef.h Thisの=0×0500が旧式のバージョン番号で
造られたコンポーネントのためのものであるなら既に申告されます。
DIDSDlg.cppで以下を試してみました。
#ifndef DIDSDLG_CPP
#define DIDSDLG_CPP
#define COMPILE_MULTIMON_STUBS
#include <multimon.h>
#endif
エラーが発生しました。
error C2065: 'HMONITOR' : 定義されていない識別子です。
error C2065: 'MONITORINFO' : 定義されていない識別子です。
StdAfx.cpp追加時とDIDSDlg.cppへの追加時では若干エラー内容が違うので
エラー内容を記載します。
●StdAfx.cpp追加時
プロジェクト 'DIDS - Win32 Debug' 用の中間ファイルおよび出力ファイルを削除しています。
--------------------構成: DIDS - Win32 Debug--------------------
リソースをコンパイル中...
コンパイル中...
StdAfx.cpp
コンパイル中...
ClientSocket.cpp
DIDS.cpp
DIDSDlg.cpp
D:\〜\DIDSDlg.cpp(1245) : error C2065: 'HMONITOR' : 定義されていない識別子です。
D:\〜\DIDSDlg.cpp(1245) : error C2146: 構文エラー : ';' が、識別子 'MonitorHandle' の前に必要です。
D:\〜\DIDSDlg.cpp(1245) : error C2065: 'MonitorHandle' : 定義されていない識別子です。
D:\〜\DIDSDlg.cpp(1246) : error C2065: 'MONITORINFO' : 定義されていない識別子です。
D:\〜\DIDSDlg.cpp(1246) : error C2146: 構文エラー : ';' が、識別子 'MonitorInfo' の前に必要です。
D:\〜\DIDSDlg.cpp(1246) : error C2065: 'MonitorInfo' : 定義されていない識別子です。
D:\〜\DIDSDlg.cpp(1301) : error C2039: 'MonitorFromPoint' : '`global namespace'' のメンバではありません。
D:\〜\DIDSDlg.cpp(1301) : error C2065: 'MonitorFromPoint' : 定義されていない識別子です。
D:\〜\DIDSDlg.cpp(1301) : error C2065: 'MONITOR_DEFAULTTOPRIMARY' : 定義されていない識別子です。
D:\〜\DIDSDlg.cpp(1302) : error C2228: '.cbSize' : 左側がクラス、構造体、共用体ではありません。
D:\〜\DIDSDlg.cpp(1303) : error C2039: 'GetMonitorInfo' : '`global namespace'' のメンバではありません。
D:\〜\DIDSDlg.cpp(1303) : error C2065: 'GetMonitorInfo' : 定義されていない識別子です。
D:\〜\DIDSDlg.cpp(1309) : error C2228: '.rcWork' : 左側がクラス、構造体、共用体ではありません。
D:\〜\DIDSDlg.cpp(1309) : error C2228: '.left' : 左側がクラス、構造体、共用体ではありません。
D:\〜\DIDSDlg.cpp(1309) : error C2228: '.rcWork' : 左側がクラス、構造体、共用体ではありません。
D:\〜\DIDSDlg.cpp(1309) : error C2228: '.top' : 左側がクラス、構造体、共用体ではありません。
D:\〜\DIDSDlg.cpp(1309) : error C2228: '.rcWork' : 左側がクラス、構造体、共用体ではありません。
D:\〜\DIDSDlg.cpp(1309) : error C2228: '.right' : 左側がクラス、構造体、共用体ではありません。
D:\〜\DIDSDlg.cpp(1309) : error C2228: '.rcWork' : 左側がクラス、構造体、共用体ではありません。
D:\〜\DIDSDlg.cpp(1309) : error C2228: '.left' : 左側がクラス、構造体、共用体ではありません。
D:\〜\DIDSDlg.cpp(1309) : error C2228: '.rcWork' : 左側がクラス、構造体、共用体ではありません。
D:\〜\DIDSDlg.cpp(1309) : error C2228: '.bottom' : 左側がクラス、構造体、共用体ではありません。
Setting.cpp
コードを生成中...
cl.exe の実行エラー
DIDS.exe - エラー 22、警告 0
●DIDSDlg.cppへの追加時
プロジェクト 'DIDS - Win32 Debug' 用の中間ファイルおよび出力ファイルを削除しています。
--------------------構成: DIDS - Win32 Debug--------------------
リソースをコンパイル中...
コンパイル中...
StdAfx.cpp
コンパイル中...
ClientSocket.cpp
DIDS.cpp
DIDSDlg.cpp
c:\program files\microsoft visual studio\vc98\include\multimon.h(73) : error C2065: 'HMONITOR' : 定義されていない識別子です。
c:\program files\microsoft visual studio\vc98\include\multimon.h(73) : error C2275: 'HDC' : typedef 識別子に、クラス メンバ アクセス演算子 (->) を使用しました。
c:\program files\microsoft visual studio\vc98\include\windef.h(239) : 'HDC' の宣言を確認してください。
c:\program files\microsoft visual studio\vc98\include\multimon.h(73) : error C2275: 'LPRECT' : typedef 識別子に、クラス メンバ アクセス演算子 (->) を使用しました。
c:\program files\microsoft visual studio\vc98\include\windef.h(292) : 'LPRECT' の宣言を確認してください。
c:\program files\microsoft visual studio\vc98\include\multimon.h(73) : error C2275: 'LPARAM' : typedef 識別子に、クラス メンバ アクセス演算子 (->) を使用しました。
c:\program files\microsoft visual studio\vc98\include\windef.h(171) : 'LPARAM' の宣言を確認してください。
c:\program files\microsoft visual studio\vc98\include\multimon.h(73) : error C2165: 'left-side modifier' : データへのポインタは変更できません。
c:\program files\microsoft visual studio\vc98\include\multimon.h(73) : error C2071: 'MONITORENUMPROC' : 記憶クラスは不正です。
c:\program files\microsoft visual studio\vc98\include\multimon.h(99) : error C2059: 構文エラー : '__stdcall'
c:\program files\microsoft visual studio\vc98\include\multimon.h(99) : error C2091: 関数は関数を返せません。
c:\program files\microsoft visual studio\vc98\include\multimon.h(99) : error C2501: 'HMONITOR' : 識別名を宣言するのに、型が指定されていません。
c:\program files\microsoft visual studio\vc98\include\multimon.h(99) : error C2373: 'HMONITOR' : 再定義されています。異なる型修飾子です。
c:\program files\microsoft visual studio\vc98\include\multimon.h(99) : error C2072: 'HMONITOR' : 関数を初期化しようとしました。
c:\program files\microsoft visual studio\vc98\include\multimon.h(100) : error C2059: 構文エラー : '__stdcall'
c:\program files\microsoft visual studio\vc98\include\multimon.h(100) : error C2091: 関数は関数を返せません。
c:\program files\microsoft visual studio\vc98\include\multimon.h(100) : error C2501: 'HMONITOR' : 識別名を宣言するのに、型が指定されていません。
c:\program files\microsoft visual studio\vc98\include\multimon.h(100) : error C2373: 'HMONITOR' : 再定義されています。異なる型修飾子です。
c:\program files\microsoft visual studio\vc98\include\multimon.h(100) : error C2072: 'HMONITOR' : 関数を初期化しようとしました。
c:\program files\microsoft visual studio\vc98\include\multimon.h(101) : error C2059: 構文エラー : '__stdcall'
c:\program files\microsoft visual studio\vc98\include\multimon.h(101) : error C2091: 関数は関数を返せません。
c:\program files\microsoft visual studio\vc98\include\multimon.h(101) : error C2501: 'HMONITOR' : 識別名を宣言するのに、型が指定されていません。
c:\program files\microsoft visual studio\vc98\include\multimon.h(101) : error C2373: 'HMONITOR' : 再定義されています。異なる型修飾子です。
c:\program files\microsoft visual studio\vc98\include\multimon.h(101) : error C2072: 'HMONITOR' : 関数を初期化しようとしました。
c:\program files\microsoft visual studio\vc98\include\multimon.h(102) : error C2629: 'int (' は不正です。
c:\program files\microsoft visual studio\vc98\include\multimon.h(114) : error C2065: 'g_pfnGetMonitorInfo' : 定義されていない識別子です。
c:\program files\microsoft visual studio\vc98\include\multimon.h(119) : error C2065: 'g_pfnMonitorFromWindow' : 定義されていない識別子です。
c:\program files\microsoft visual studio\vc98\include\multimon.h(120) : error C2065: 'g_pfnMonitorFromRect' : 定義されていない識別子です。
c:\program files\microsoft visual studio\vc98\include\multimon.h(121) : error C2065: 'g_pfnMonitorFromPoint' : 定義されていない識別子です。
c:\program files\microsoft visual studio\vc98\include\multimon.h(184) : error C2143: 構文エラー : ';' が '__stdcall' の前に必要です。
c:\program files\microsoft visual studio\vc98\include\multimon.h(184) : error C2501: 'HMONITOR' : 識別名を宣言するのに、型が指定されていません。
c:\program files\microsoft visual studio\vc98\include\multimon.h(196) : error C2143: 構文エラー : ')' が 'constant' の前に必要です。
c:\program files\microsoft visual studio\vc98\include\multimon.h(196) : error C2059: 構文エラー : ')'
c:\program files\microsoft visual studio\vc98\include\multimon.h(202) : error C2143: 構文エラー : ';' が '__stdcall' の前に必要です。
c:\program files\microsoft visual studio\vc98\include\multimon.h(202) : error C2501: 'HMONITOR' : 識別名を宣言するのに、型が指定されていません。
c:\program files\microsoft visual studio\vc98\include\multimon.h(202) : error C2086: 'HMONITOR' : 再定義されました。
c:\program files\microsoft visual studio\vc98\include\multimon.h(202) : 'HMONITOR' の宣言を確認してください。
c:\program files\microsoft visual studio\vc98\include\multimon.h(214) : error C2143: 構文エラー : ')' が 'constant' の前に必要です。
c:\program files\microsoft visual studio\vc98\include\multimon.h(214) : error C2059: 構文エラー : ')'
c:\program files\microsoft visual studio\vc98\include\multimon.h(220) : error C2143: 構文エラー : ';' が '__stdcall' の前に必要です。
c:\program files\microsoft visual studio\vc98\include\multimon.h(220) : error C2501: 'HMONITOR' : 識別名を宣言するのに、型が指定されていません。
c:\program files\microsoft visual studio\vc98\include\multimon.h(220) : error C2086: 'HMONITOR' : 再定義されました。
c:\program files\microsoft visual studio\vc98\include\multimon.h(220) : 'HMONITOR' の宣言を確認してください。
c:\program files\microsoft visual studio\vc98\include\multimon.h(229) : error C2143: 構文エラー : ')' が 'constant' の前に必要です。
c:\program files\microsoft visual studio\vc98\include\multimon.h(229) : error C2059: 構文エラー : ')'
c:\program files\microsoft visual studio\vc98\include\multimon.h(242) : error C2146: 構文エラー : ')' が、識別子 'hMonitor' の前に必要です。
c:\program files\microsoft visual studio\vc98\include\multimon.h(242) : warning C4229: 旧形式が使用されています : データの修飾子は無視されます。
c:\program files\microsoft visual studio\vc98\include\multimon.h(242) : error C2059: 構文エラー : ')'
c:\program files\microsoft visual studio\vc98\include\multimon.h(243) : error C2143: 構文エラー : ';' が '{' の前に必要です。
c:\program files\microsoft visual studio\vc98\include\multimon.h(243) : error C2447: 'PCH creation point' : 関数ヘッダがありません (旧形式の仮引数リスト?)
c:\program files\microsoft visual studio\vc98\include\multimon.h(328) : error C2143: 構文エラー : ')' が 'constant' の前に必要です。
c:\program files\microsoft visual studio\vc98\include\multimon.h(331) : error C2059: 構文エラー : ')'
D:\〜\DIDSDlg.cpp(1245) : error C2146: 構文エラー : ';' が、識別子 'MonitorHandle' の前に必要です。
D:\〜\DIDSDlg.cpp(1245) : error C2065: 'MonitorHandle' : 定義されていない識別子です。
Setting.cpp
コードを生成中...
cl.exe の実行エラー
DIDS.exe - エラー 48、警告 1
#include <windows.h>
を追加することにエラーを解消できました。
ポン太さん、みいさん、yoh2さん、ありがとうございました。
感謝です。<m(__)m>
間違いです。
処理がコメントのままでした。
ツイート | ![]() |