メインコンテンツ

MATLAB 関数からの C/C++ コードの生成

この例では、MATLAB® 関数から C/C++ コードを生成する場合の推奨ワークフローを示します。このワークフローの手順は次のとおりです。

  1. コード生成用の MATLAB コードを準備します。

  2. MEX 関数を生成およびテストします。

  3. C/C++ コードを生成および検査します。

この例では、codegen コマンドを使用して、コマンド ラインで C/C++ コードを生成します。MATLAB Coder™ アプリを使用したコードの生成方法の詳細については、MATLAB Coder アプリを使用した C コードの生成を参照してください。

MATLAB コードとサンプル データの作成

この手順は、この例の目的のために必要なものであり、コード生成ワークフローの一般的な手順ではありません。

入力信号に対して平均化フィルターとして機能する MATLAB 関数 averagingFilterML を作成します。この関数は、信号値の入力ベクトルを取り、フィルター処理された値の出力ベクトルを返します。出力ベクトルは、入力ベクトルと同じサイズです。関数 averagingFilterML は変数 slider を使用して 16 の信号値のスライディング ウィンドウを表し、各ウィンドウ位置の平均信号値を計算します。

type averagingFilterML
function y = averagingFilterML(x)
slider = zeros(16,1);
y = zeros(size(x));
for i = 1:numel(x)
    slider(2:end) = slider(1:end-1); % move one position in the buffer
    slider(1) = x(i); % Add a new sample value to the buffer
    y(i) = sum(slider)/numel(slider); % write the average of the current window to y
end
end

ノイズを含む正弦波をサンプル データとして生成し、averagingFilterML を使用してノイズを含むデータをフィルター処理します。ノイズを含むデータとフィルター処理されたデータを同じ Figure ウィンドウにプロットします。

v = 0:0.00614:2*pi;
x = sin(v) + 0.3*rand(1,numel(v));
y = averagingFilterML(x);
plot(x,"red");
hold on
plot(y,"blue");
hold off;

Figure contains an axes object. The axes object contains 2 objects of type line.

手順 1: コード生成用の MATLAB コードの準備

関数 averagingFilterML の名前を averagingFilterCG に変更します。averagingFilterCG%#codegen 命令を追加して、コード生成に固有の警告とエラーを特定するように MATLAB コード アナライザーに指示します。コード生成では、入力変数の型を定義しておく必要があります。arguments ブロックを使用して、入力を doubles の非有界のベクトルとして指定します。

type averagingFilterCG
function y = averagingFilterCG(x) %#codegen
arguments
    x (1,:) double
end
slider = zeros(16,1);
y = zeros(size(x));
for i = 1:numel(x)
    slider(2:end) = slider(1:end-1); % move one position in the buffer
    slider(1) = x(i); % Add a new sample value to the buffer
    y(i) = sum(slider)/numel(slider); % write the average of the current window to y
end
end

手順 2: MEX 関数の生成とテスト

C/C++ コードを生成する前に、MEX 関数を生成してテストすることが重要です。C/C++ コードを生成する前に MATLAB で MEX 関数を実行することにより、生成されたコード内では診断が非常に困難な実行時エラーを検出して修正できます。さらに、MEX 関数を使用して、生成されたコードが元の MATLAB コードと同様に機能することを確認できます。

codegen コマンドを使用して、averagingFilterCG から MEX 関数を生成します。元の MATLAB 関数に渡したのと同じ入力を使用して MEX 関数をテストし、結果を比較します。MEX 関数は同じ出力を生成します。

codegen averagingFilterCG
Code generation successful.
z = averagingFilterCG_mex(x);
plot(x,"red");
hold on
plot(z,"blue");
hold off;

Figure contains an axes object. The axes object contains 2 objects of type line.

手順 3: C/C++ コードの生成と検査

-config:lib オプションを指定した codegen コマンドを使用し、スタンドアロン C ライブラリを生成します。生成された C コードで関数 averagingFilterCG を検査します。

codegen -config:lib averagingFilterCG
Code generation successful.
type(fullfile("codegen","lib","averagingFilterCG","averagingFilterCG.c"))
/*
 * File: averagingFilterCG.c
 *
 * MATLAB Coder version            : 25.1
 * C/C++ source code generated on  : 13-Jul-2025 16:32:10
 */

/* Include Files */
#include "averagingFilterCG.h"
#include "averagingFilterCG_emxutil.h"
#include "averagingFilterCG_types.h"
#include <string.h>

/* Function Definitions */
/*
 * Arguments    : const emxArray_real_T *x
 *                emxArray_real_T *y
 * Return Type  : void
 */
void averagingFilterCG(const emxArray_real_T *x, emxArray_real_T *y)
{
  double slider[16];
  double b_slider[15];
  const double *x_data;
  double *y_data;
  int i;
  int k;
  int loop_ub;
  x_data = x->data;
  memset(&slider[0], 0, 16U * sizeof(double));
  loop_ub = y->size[0] * y->size[1];
  y->size[0] = 1;
  y->size[1] = x->size[1];
  emxEnsureCapacity_real_T(y, loop_ub);
  y_data = y->data;
  loop_ub = x->size[1];
  for (i = 0; i < loop_ub; i++) {
    y_data[i] = 0.0;
  }
  loop_ub = x->size[1];
  for (i = 0; i < loop_ub; i++) {
    double b_y;
    memcpy(&b_slider[0], &slider[0], 15U * sizeof(double));
    /*  move one position in the buffer */
    b_y = x_data[i];
    slider[0] = b_y;
    /*  Add a new sample value to the buffer */
    for (k = 0; k < 15; k++) {
      double d;
      d = b_slider[k];
      slider[k + 1] = d;
      b_y += d;
    }
    y_data[i] = b_y / 16.0;
    /*  write the average of the current window to y */
  }
}

/*
 * File trailer for averagingFilterCG.c
 *
 * [EOF]
 */

または、-config:lib オプションと -lang:C++ オプションを指定した codegen コマンドを使用し、スタンドアロン C++ ライブラリを生成します。生成された C++ コードの関数 averagingFilterCG を生成された C コードの関数と比較します。

codegen -config:lib -lang:c++ averagingFilterCG
Code generation successful.
type(fullfile("codegen","lib","averagingFilterCG","averagingFilterCG.cpp"))
//
// File: averagingFilterCG.cpp
//
// MATLAB Coder version            : 25.1
// C/C++ source code generated on  : 13-Jul-2025 16:32:13
//

// Include Files
#include "averagingFilterCG.h"
#include "coder_array.h"
#include <algorithm>
#include <cstring>

// Function Definitions
//
// Arguments    : const coder::array<double, 2U> &x
//                coder::array<double, 2U> &y
// Return Type  : void
//
void averagingFilterCG(const coder::array<double, 2U> &x,
                       coder::array<double, 2U> &y)
{
  double slider[16];
  double b_slider[15];
  int loop_ub;
  std::memset(&slider[0], 0, 16U * sizeof(double));
  y.set_size(1, x.size(1));
  loop_ub = x.size(1);
  for (int i{0}; i < loop_ub; i++) {
    double b_y;
    y[i] = 0.0;
    std::copy(&slider[0], &slider[15], &b_slider[0]);
    //  move one position in the buffer
    b_y = x[i];
    slider[0] = b_y;
    //  Add a new sample value to the buffer
    for (int k{0}; k < 15; k++) {
      double d;
      d = b_slider[k];
      slider[k + 1] = d;
      b_y += d;
    }
    y[i] = b_y / 16.0;
    //  write the average of the current window to y
  }
}

//
// File trailer for averagingFilterCG.cpp
//
// [EOF]
//

参考

トピック