生成されたコードにおける列挙型のカスタマイズ
生成コードにおける列挙をカスタマイズするには、MATLAB® 列挙クラス定義の静的メソッド セクションで、次の表に示すカスタマイズ バージョンのメソッドを提供します。表には以下も示されています。
メソッドを MATLAB 列挙クラス定義で明示的に実装していない場合にメソッドによって返される既定値。実装が提供されていない場合、コード ジェネレーターは、この既定値がメソッドによって返されるものと想定します。
メソッドによって返される可能性があるすべての値とその生成コードへの影響。
メソッド | 説明 | 戻り値 |
---|---|---|
generateEnumClass | 列挙クラスを生成するかどうかを指定します。通常の C の列挙を含む C++ コードの生成 (MATLAB Coder)を参照してください。 |
|
| 生成コードでクラス名を接頭辞にするかどうかを指定します。生成される列挙値の名前にクラス名の接頭辞を含めるを参照してください。 |
|
| 生成コードにおける列挙のカスタム名を指定します。ターゲット言語が C++ の場合、生成コードにおける列挙の名前空間も指定します。カスタムの列挙名の指定 (MATLAB Coder)を参照してください。 | 既定の戻り値は |
| 既定の列挙値を返します。既定の列挙値の指定を参照してください。 | 既定の戻り値は列挙クラス定義の最初の値です。 |
| 列挙型をエクスポートするかインポートするかを指定します。詳細については、以下を参照してください。
|
|
| インポートまたはエクスポートされる列挙型の定義を含むヘッダー ファイルを指定します。詳細については、以下を参照してください。
. | 既定の戻り値は |
| インポートされる列挙型について、ビルド時、つまりソース コードの生成後に列挙メンバーの値を変更できるかどうかを指定します。列挙メンバーの値をビルド時に変更 (MATLAB Coder)を参照してください。 |
|
通常の C の列挙を含む C++ コードの生成
列挙クラスをサポートする言語標準 (C++11 以降) を使用してコードを生成すると、MATLAB 列挙クラスは C++ の列挙クラスに変換されます。以下に例を示します。
enum class MyEnumClass16 : short
{
Orange = 0, // Default value
Yellow,
Pink
};
代わりに通常の C の列挙を生成するには、false
を返す generateEnumClass
メソッドを指定します。以下に例を示します。
classdef MyEnumClass16 < int16 enumeration Orange(0), Yellow(1), Pink(2) end % particular enum opting out methods(Static) function y = generateEnumClass() y = false; end end end
これで、生成される C++ コードに通常の C の列挙が含まれます。
enum MyEnumClass16 : short
{
Orange = 0, // Default value
Yellow,
Pink
};
生成される列挙値の名前にクラス名の接頭辞を含める
既定では、生成された列挙型の値の名前はクラス名の接頭辞を含みません。以下に例を示します。
enum LEDcolor
{
GREEN = 1,
RED
};
typedef enum LEDcolor LEDcolor;
クラス名の接頭辞を含めるには、true
を返す addClassNameToEnumNames
メソッドを指定します。以下に例を示します。
classdef LEDcolor < int32 enumeration GREEN(1), RED(2) end methods(Static) function y = addClassNameToEnumNames() y=true; end end end
生成された型定義で、列挙型の値の名前にはクラス名の接頭辞 LEDcolor
が含まれています。
enum LEDcolor
{
LEDcolor_GREEN = 1,
LEDcolor_RED
};
typedef enum LEDcolor LEDcolor;
メモ
列挙クラスを生成する場合 (C++11 以降の標準)、コード ジェネレーターはこの静的メソッドを無視します。
カスタムの列挙名の指定
R2025a 以降
生成コードにおける MATLAB 列挙に対して、ターゲット言語に基づいて構成可能なカスタム名を指定できます。
ターゲット言語が C である場合について考えます。入力 "C"
が渡された場合にカスタム名を string として返す generatedCodeIdentifier
メソッドの実装を提供します。
ターゲット言語が C++ の場合は、列挙のカスタム名と名前空間の両方を指定できます。入力 "C++"
が渡されたときにカスタム名と名前空間を "mynamespace::myname"
の形式の string として返す generatedCodeIdentifier
メソッドの実装を提供します。
たとえば、名前空間 matlabNamespace
で次の MATLAB 列挙を定義します。
% Defined in file +matlabNamespace/CustomEnumName.m classdef CustomEnumName < int32 enumeration Red(0), Blue(1), Green(2) end methods(Static) function n = generatedCodeIdentifier(lang) if lang == "C++" n = "cppNamespace::MyCppEnum"; else n = "myCEnum"; end end end end
この列挙を使用するエントリポイント関数 xCustomEnumName
を定義します。
function out = xCustomEnumName out = matlabNamespace.CustomEnumName.Green; end
最初に、このエントリポイント関数の C ソース コードを生成します。
codegen -config:lib -c xCustomEnumName -report
生成される C の列挙定義は次のようになります。
enum myCEnum
{
Red = 0, /* Default value */
Blue,
Green
};
次に、このエントリポイント関数の C++ ソース コードを生成します。
codegen -lang::c++ -config:lib -c xCustomEnumName -report
生成される C++ の列挙定義は次のようになります。
namespace cppNamespace {
enum class MyCppEnum : int
{
Red = 0, // Default value
Blue,
Green
};
}
既定の列挙値の指定
列挙型にキャストされた変数の値が列挙型の値のいずれとも一致しない場合には次のようになります。
生成された MEX ではエラーを報告します。
生成された C/C++ コードでは、変数の値を列挙型の既定値に置き換えます。
別に指定しない限り、列挙型の既定値が列挙型クラス定義での最初の値になります。異なる既定値を指定するには、独自の getDefaultValue
メソッドを methods セクションに追加します。この例では、最初の列挙型メンバー値は LEDcolor.GREEN
ですが、getDefaultValue
メソッドは LEDcolor.RED
を返します。
classdef LEDcolor < int32 enumeration GREEN(1), RED(2) end methods (Static) function y = getDefaultValue() y = LEDcolor.RED; end end end
外部ヘッダー ファイルからの列挙型定義のインポート
列挙型が外部ヘッダー ファイルで定義されていることを指定するには、ヘッダー ファイルのパスを空でない string として返すカスタマイズされた getHeaderFile
メソッドを提供します。この例では、LEDcolor
が外部ファイル my_LEDcolor.h
で定義されるように指定します。
classdef LEDcolor < int32 enumeration GREEN(1), RED(2) end methods(Static) function y = getHeaderFile() y = "my_LEDcolor.h"; end end end
この場合、コード ジェネレーターで列挙の定義は出力されません。この定義を提供する my_LEDcolor.h
ファイルを提供しなければなりません。以下に例を示します。
enum LEDcolor
{
GREEN = 1,
RED
};
typedef enum LEDcolor LEDcolor;
MATLAB 列挙 LEDcolor
を MATLAB 名前空間 nmsp
内に配置して C++ コードを生成する場合は、コード生成でこの列挙の名前が保持され、生成されたコードの C++ 名前空間 nmsp
内に配置されます。したがって、指定するヘッダー ファイルで、名前空間 nmsp
内のこの列挙を定義する必要があります。
外部ヘッダー ファイルへの列挙型定義のエクスポート
R2025a 以降
指定したヘッダー ファイルに列挙型の定義を出力するようにコード ジェネレーターに指示できます。MATLAB 列挙クラス定義で以下の実装を提供します。
string の
"Exported"
を返すgetDataScope
メソッドヘッダー ファイルの名前を空でない string として返す
getHeaderFile
メソッド
たとえば、次の MATLAB 列挙クラス exportedEnum
を定義します。
classdef ExportedEnum < int32 enumeration red (1) blue (2) green (3) yellow (4) end methods(Static) function out = getDataScope() out = "Exported"; end function hFile = getHeaderFile() hFile = "exportedEnumHeader.h"; end end end
この列挙を使用するエントリポイント関数 xExportedEnum
を定義します。
function out = xExportedEnum(in) t = local(in); out = int32(t); end function out = local(in) t = ExportedEnum.green; if (in > 9) out = t; else out = ExportedEnum.red; end end
xExportedEnum
の C++ ソース コードを生成します。
codegen -lang:c++ -config:lib -c xExportedEnum -args 0 -report
生成されたファイルを検証します。C++ の列挙クラス ExportedEnum
はヘッダー ファイル exportedEnumHeader.h
で定義されています。
列挙メンバーの値をビルド時に変更
R2025a 以降
列挙をインポートとして指定 (外部ヘッダー ファイルからの列挙型定義のインポート (MATLAB Coder)を参照) すると、その列挙の定義はコード ジェネレーターで生成される C/C++ ソース ファイルに含まれません。生成されたソース コードをビルドするときに、その定義を含むヘッダー ファイルを提供する必要があります。
一般的な状況においては、ヘッダー ファイルの列挙メンバーの値は MATLAB 列挙クラス定義の値と一致しなければなりません。これは、定数畳み込みを実行して生成コードを最適化しようとしたときに、コード ジェネレーターで生成されるソース コードに MATLAB 列挙メンバーの値がハードコードされることがあるためです。
一方、カスタム ヘッダー ファイルでインポートされる列挙メンバーの値を生成コードのビルド時に変更するように指定することができます。MATLAB 列挙クラス定義で、true
を返す isTunableInCode
静的メソッドの実装を提供します。この戻り値は、列挙メンバーを伴う式については定数畳み込みを実行せず、元の列挙メンバー自体への参照を保持するようにコード ジェネレーターに指示します。この動作により、最終的なビルド アーティファクト (MEX、ライブラリ、または実行可能ファイル) において、現在のヘッダー ファイルで提供される列挙メンバーの値を使用する計算を実行できるようになります。
たとえば、インポートと調整可能の両方として指定された次の MATLAB 列挙クラス定義について考えてみます。
classdef Colors < int32 enumeration Red(0), Blue(1), Green(2) end methods(Static) function y = getHeaderFile() y = 'Header.h'; % making this imported end function y = isTunableInCode() y = true; % making this tunable end end end
Colors
列挙を使用するエントリポイント関数を定義します。
function out = xColors t = 2; if (t == Colors.Green) out = 1; elseif (t == Colors.Red) out = 2; else out = 6; end end
xColors
の C++ ソース コードを生成します。
codegen -lang:c++ -c -config:lib xColors -report
生成された xColors
エントリポイント関数を検証します。生成されたファイルで列挙メンバー自体のインスタンスがすべて保持されています。
double xColors()
{
double out;
if (static_cast<int>(Colors::Green) == 2) {
out = 1.0;
} else if (static_cast<int>(Colors::Red) == 2) {
out = 2.0;
} else {
out = 6.0;
}
return out;
}
次に、列挙の isTunableInCode
メソッドをコメント アウトしてコードを再度生成します。今回はコード ジェネレーターによって列挙メンバーの定数畳み込みが実行され、生成コードがさらに最適化されて 1 行に減っています。
double xColors()
{
return 1.0;
}
この例から、列挙を調整可能として指定すると、定数畳み込みの最適化に依存する最適化がそれ以降生成コードで実行されなくなる可能性があることもわかります。
定数の条件式と到達不能コード
xColors
のスタティック ライブラリを生成するには、次の C++ 列挙クラス定義を含むファイル Header.h
を作成します。
enum class Colors : int
{
Green = 0, // Default value
Blue,
Red
};
コードを生成してスタティック ライブラリをビルドするには、次のコマンドを実行します。
codegen -lang:c++ -config:lib xColors -report
Warning: C++ Compiler produced warnings. See the build log for further details. Code generation successful (with warnings): View report
与えられた Colors
列挙の実装では、static_cast<int>(Colors::Green) == 2
などの条件式が定数となるため、C/C++ コンパイラから次の警告がスローされます。
warning C4127: conditional expression is constant
また、このコード パターンにより、条件ブロックの特定の分岐が到達不能になる可能性があります。たとえば、Colors
の現在の定義では、生成される xColors
関数の else
分岐は到達不能になります。
定数の条件式と到達不能な分岐により、調整可能な列挙の生成コードは MISRA™ C:2012 Rule 2.1 と Rule 14.3、MISRA C++:2008 Rule 0-1-1 などの特定のコーディング規約のルールに違反することになります。
参考
トピック
- スーパークラス メソッドとプロパティの修正
- 列挙型のコードの生成
- コード生成に使用する言語標準の変更 (MATLAB Coder)