メインコンテンツ

生成されたコードにおける列挙型のカスタマイズ

生成コードにおける列挙をカスタマイズするには、MATLAB® 列挙クラス定義の静的メソッド セクションで、次の表に示すカスタマイズ バージョンのメソッドを提供します。表には以下も示されています。

  • メソッドを MATLAB 列挙クラス定義で明示的に実装していない場合にメソッドによって返される既定値。実装が提供されていない場合、コード ジェネレーターは、この既定値がメソッドによって返されるものと想定します。

  • メソッドによって返される可能性があるすべての値とその生成コードへの影響。

メソッド説明戻り値
generateEnumClass

列挙クラスを生成するかどうかを指定します。通常の C の列挙を含む C++ コードの生成 (MATLAB Coder)を参照してください。

true (既定) — 生成される C++ コードに列挙クラスが含まれます。

false — 生成される C++ コードに通常の C スタイルの列挙が含まれます。

addClassNameToEnumNames

生成コードでクラス名を接頭辞にするかどうかを指定します。生成される列挙値の名前にクラス名の接頭辞を含めるを参照してください。

false (既定) — 接頭辞は使用されません。

true — 接頭辞が使用されます。

generatedCodeIdentifier (R2025a 以降)

生成コードにおける列挙のカスタム名を指定します。ターゲット言語が C++ の場合、生成コードにおける列挙の名前空間も指定します。カスタムの列挙名の指定 (MATLAB Coder)を参照してください。

既定の戻り値は "" です。

getDefaultValue

既定の列挙値を返します。既定の列挙値の指定を参照してください。

既定の戻り値は列挙クラス定義の最初の値です。

getDataScope (R2025a 以降)

列挙型をエクスポートするかインポートするかを指定します。詳細については、以下を参照してください。

"Auto" (既定) —

  • getHeaderFile メソッドを使用して空でないヘッダー ファイル名が指定されている場合、コード ジェネレーターは、そのファイルから列挙型定義をインポートします。

  • それ以外の場合、コード ジェネレーターは、ローカルまたは *_types.h ファイルのいずれかに型定義を出力します。

"Imported" — コード ジェネレーターは、提供されたヘッダー ファイルから列挙型定義をインポートします。このヘッダー ファイルのパスを空でない string として返す getHeaderFile メソッドも提供しなければなりません。

"Exported"getHeaderFile メソッドを使用して空でないヘッダー ファイル名が指定されている場合、コード ジェネレーターは、そのファイルに列挙定義を生成します。それ以外の場合、コード ジェネレーターは、*_types.h ファイルに列挙定義を生成します。

getHeaderFile

インポートまたはエクスポートされる列挙型の定義を含むヘッダー ファイルを指定します。詳細については、以下を参照してください。

.

既定の戻り値は "" です。

isTunableInCode (R2025a 以降)

インポートされる列挙型について、ビルド時、つまりソース コードの生成後に列挙メンバーの値を変更できるかどうかを指定します。列挙メンバーの値をビルド時に変更 (MATLAB Coder)を参照してください。

false (既定) — 列挙メンバーの値をビルド時に変更できません。

true — 列挙メンバーの値をビルド時に変更できます。

通常の 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 などの特定のコーディング規約のルールに違反することになります。

参考

トピック