[ C++で開発 ]

Visual C++雑多メモ

標準C関係

標準Cライブラリ

math.hのマクロ定義値がない

M_PIなどの#defineがデフォルトでは利用できない。<math.h>をインクルードする前に、_USE_MATH_DEFINESを定義しておく。

#define _USE_MATH_DEFINES
#include <math.h>

strcpy、sprinitfなどでコンパイル時に警告発生(unsafe)

VC++ 2005以上

現象

標準Cライブラリのstrcpy、sprintfなどを使用していると、コンパイル時に警告が発生します。バッファー・オーバーランの原因になるので、安全な別関数(strcpy_s、sprintf_sなど)の使用を推奨してきます。

MSDNの解説ページ[CRTのセキュリティ強化]

しかし・・・

対策

警告なので無視するのも一手ですが、警告が残ったままでは気持ちが悪いと感じるお行儀よいプログラミングをする人には「大迷惑」なので、コンパイル時にデファイン_CRT_SECURE_NO_WARNINGSを指定します。

mkdir, closeなどPOSIX関数でコンパイル時に警告発生(unsafe)

VC++ 2005以上

現象

POSIXライブラリのopen, mkdirなどを使用していると、コンパイル時に警告が発生します。別関数(_open, _mkdirなど)の使用を推奨してきます。

要調査: C++標準におけるPOSIXライブラリの定義

MSDNの解説ページ[使用を推奨されていないCRT関数]

対策

コンパイル時にデファイン _CRT_NONSTDC_NO_DEPRECATEを定義する

標準C++関係

エディタ

外部エディタとの連携(Emacs編)

VC++ 2005からはEmacsキーバインドが選択できるようになったのですが、それでもEmacsで編集したいときの連携を設定する方法です。

VC++ 2010では、Emacsキーバインドが標準で搭載されなくなってしまいました。別途拡張機能でダウンロード可能(ただしExpress版を除く)

参考のWebページ「Memoranda on Visual Studio 2005 Express Editions for Emacs Users」に詳しく設定方法が書いてありますので、ここはメモだけ。

[ツール]メニュー→[外部ツール...]で「外部ツール」ダイアログが表われるので、[追加]ボタンを押し、以下の設定を記述したのち[適用]ボタンを押します。

タイトル
Meadow
コマンド
C:\Meadow\Meadow2.bat
引数
+$(CurLine) $(ItemPath)
初期ディレクトリ
$(ItemDir)

設定後、[ツール]メニューにタイトルで設定した名称(Meadow)が表われるようになります。

Meadowで保存時に毎回ダイアログが出ないようにするには、[ツール]メニュー→[オプション]で表われるダイアログの左側ペインで[環境]→[ドキュメント]を選択し、右側ペインで[環境内で変更されていない場合に変更を自動的に読み込む(A)」にチェックを入れます。

注)コマンドではMeadow起動用に個人作成のバッチを指定していますが、直接Meadowの実行ファイルでもかまいません

参考

namespaceのインデント制御付加

大規模プログラムでは、階層化した名前空間(namespace)が不可欠ですが、VC++のエディタはnamespaceのインデントを抑止することができず、いたずらにインデントが深くなってしまいます。

namespace service {
    namespace weather {
        namespace sensor {
            class SensorMonitor : public Monitor {
            public:
                SensorMonitor();
                :
            };
        }
    }
}

インデントの設定ではこれを抑止することができず、これは結構困った問題です。

参考になる回避策について、以下URLに議論がありました。参考までに簡単に紹介します。

苦しい回避方法

見苦しさを伴う回避方法があるにはあります。

インデントレベルを1つだけに抑える
namespace service { namespace weather { namespace sensor {
    class SensorMonitor : public Monitor {
        :
    };
}}}

とっても許容したくはありませんが、回避策にはなります。それでもインデントが発生してしまいますが・・・。

空行を1つ入れる
namespace service
{;
namespace weather
{;
namespace sensor
{;
class SensorMonitor : public Monitor {
    :
};
}
}
}

トリッキーですが、インデントを0にすることができる回避策です。ソースコードにインデント制御のための無意味な記述が生じるのでとても許容したくはありませんが・・・

namespace宣言をマクロに置き換える

詳細は参考URLを参照、これも許容したくはありません。

ユーザーマクロでインデントを修正

詳細は参考URLを参照、これならソースコードを汚染せずににインデントを制御できそうです。マクロについては、Express版では利用できないようです。

DLLの作成

DLL公開ヘッダーに定義するシンボル公開用修飾子

Visual C++では、DLLを定義する際に、DLLが公開する関数・クラスを定義したヘッダーファイルに特別な修飾を付ける必要があります。

DLL自体をビルドするときは、ヘッダーファイルで公開する関数・クラスを宣言・定義する際に__declspec(dllexport)を付けます。

DLLビルド用ヘッダー定義

void __declspec(dllexport) myFunc();

class __declspec(dllexport) MyClass {};

DLLを使用する側をビルドするときは、DLLが提供するヘッダーファイルで公開する関数・クラスを宣言する際に、_declspec(dllimport)を付けます。

DLL提供用ヘッダー定義

void __declspec(dllimport) myFunc();

class __declspec(dllimport) MyClass {};

ヘッダーファイルを2重(dllimport用とdllexport用)に作成することは作業効率・保守効率上好ましくないので、1つのヘッダーファイルで条件コンパイルによって切り替えます。

#ifdef _USRDLL
#  ifdef MYDLL_EXPORT
#    define EXPORT __declspec(dllexport)
#  else
#    define EXPORT __declspec(dllimport)
#  endif // MYDLL_EXPORT
#endif // _USRDLL

void EXPORT myFunc();

class EXPORT MyClass {};

VC++ではDLLプロジェクトを作成すると、_USRDLLというプリプロセッサシンボルを定義するのでこれを利用してDLLを使用するときはこれを定義します(呼び出し側も定義する必要があります)。こうすると、同じヘッダーファイルをDLLではなく利用することができます。

次にDLL自体をビルドするプロジェクトではMYDLL_EXPORTを定義します。

VC++ 9のプロジェクトウィザードでシンボルのエクスポートを選ぶと生成される制御

VC++プロジェクトファイル

VC++のプロジェクトファイルのフォーマットに関するメモです。数が増えてくるとGUI上で1つ1つちまちまと同じ修正をしてまわるのは苦痛なので、ツールで一括変換する際にフォーマットを知っておくと便利です。

vcprojファイルのフォーマット

XMLフォーマットです。

インクルードパス、プリプロセッサ定義、ライブラリパス、ライブラリを修正したいというのが通常なので、それぞれのXML上の定義を見てみます。

<?xml version="1.0" encoding="shift_jis"?>
<VisualStudioProject ProjectType="Visual C++" Version="7.10" ...>
    <Configurations>
        <Configuration Name="Debug|Win32" ...>
            <Tool Name="VCCLCompilerTool"
                  AdditionalIncludeDirectories="..\include;&quot;$(ACE_ROOT)&quot;"
                  PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
                  ...
            />
            <Tool Name="VCLinkerTool"
                  AdditionalDependencies="TAO_CosNamingd.lib TAOd.lib ACEd.lib"
                  AdditionalLibraryDirectories="&quot;$(ACE_ROOT)\lib&quot;"
                  ...
            />
            ...
        </Configuration>
    </Configurations>
</VisualStudioProject>

基本はGUIで入力したとおりですが、環境変数を使用している場合、””で囲まれ、さらに”がXMLの&quot;で表現されます。