【C++】__cplusplusマクロの意味

C++
本記事で分かること
  • 『__cplusplus』の意味
  • C言語とC++の呼び出し規約のサンプルプログラム

C/C++のコンパイラでは『 __cplusplus 』というプリプロセッサマクロが事前定義されます。実際の製品コードの中でもたまに見かけることがあります。本投稿では、この『 __cplusplus』マクロについて解説します。

実行環境は下表の通りです。

開発環境Microsoft Visual Studio Community 2019 Version 16.11.7
OSWindows 10 バージョン21H1
実行環境
スポンサーリンク
スポンサーリンク

使い方と意味

『 __cplusplus 』 は、C/C++のソースコード上で記述します。ifdef、ifndefと合わせて使用します。よく見かける使い方は下記です。

#ifdef __cplusplus
      C++独自仕様のコード
#else
      C言語独自仕様のコード
#endif

具体例としては、DLLで関数をエクスポートする際、名前マングリング有りと無しの関数を用意したい場合などに用いられます。

サンプルコード

サンプルで説明します。まずは、DLL側のコードです。エクスポートする関数は”SayHello”と”SayHello1″の2つですが、2関数には以下の違いがあります。

  • SayHello …名前マングリング有り
  • SayHello1 …名前マングリング無し

下記コードは、C++ソースファイルのため、コンパイル時に『 __cplusplus 』マクロが事前定義されます。

#include <stdio.h>

__declspec (dllexport) void SayHello(void)
{
	printf("[SayHello]Hello!\n");
}

#ifdef __cplusplus                // C++としてのコンパイルか
extern "C" __declspec (dllexport) void SayHello1(void)
{
	printf("[SayHello1]__cplusplus defined.\n");
	printf("[SayHello1]Hello!\n");
}
#endif

dumpbinによりエクスポート状況を確認すると、2関数がエクスポートされています。”SayHello”は『 __cplusplus 』を使用していないため、C++としてビルドされ、名前マングリングされています。他方、”SayHello1″は『 __cplusplus 』が有効のため、内部の”SayHello1″関数定義が実行されています。extern “C”が付加されているので、C言語の呼び出し規約による定義となり、名前マングリング無しになります。

テストメインプログラムからの関数呼び出し

作成したDLL(TestDll.dll)をテスト用のメインプログラムから呼び出します。

#include <stdio.h>
#include <Windows.h>

void main(void)
{
	HMODULE hm = NULL;
	FARPROC proc1 = NULL;
	FARPROC proc2 = NULL;

	hm = LoadLibrary(L"TestDll.dll");
	if (hm == NULL)
	{
		printf("abnormal exit-1.\n");
		return;
	}
	proc1 = GetProcAddress(hm, "?SayHello@@YAXXZ");      // 名前マングリング有りの関数
	proc2 = GetProcAddress(hm, "SayHello1");             // 名前マングリング無しの関数

	if (proc1 == NULL || proc2 == NULL)
	{
		printf("abnormal exit-2.\n");
		return;
	}
	proc1();
	proc2();
	FreeLibrary(hm);
	return;
}

実行結果は、以下の通りです。proc1()の呼び出しで、”SayHello”が実行されて、proc2()の呼び出しでは、”SayHello1″が実行されています。

まとめ

『 __cplusplus 』マクロを使い、名前マングリング有り無しの関数をエクスポートするDLLサンプルを作成しました。C言語とC++を混在して使う場面は、実際の現場ではよくあります。基本的にはC++で作成したプログラムでも、C言語でインターフェースしたい場合には、この仕掛けを理解し、活用してください。

参考リンク

定義済みマクロ
Microsoft C++ コンパイラの定義済みプリプロセッサ マクロを一覧にして説明します。

コメント

タイトルとURLをコピーしました