Main Content

MATLAB 함수에서 C/C++ 코드 생성하기

이 예제에서는 MATLAB® 함수에서 C/C++ 코드를 생성하는 데 권장되는 워크플로를 보여줍니다. 이 워크플로의 단계는 다음과 같습니다.

  1. 코드 생성을 위해 MATLAB 코드를 준비합니다.

  2. MEX 함수를 생성하고 테스트합니다.

  3. C/C++ 코드를 생성하고 검사합니다.

이 예제에서는 codegen 명령을 사용하여 명령줄에서 C/C++ 코드를 생성합니다. MATLAB Coder 앱을 사용하여 코드를 생성하는 방법은 Generate C Code by Using the MATLAB Coder App 항목을 참조하십시오.

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;

1단계: 코드 생성을 위한 MATLAB 코드 준비

averagingFilterML 함수의 이름을 averagingFilterCG로 바꿉니다. MATLAB 코드 분석기가 코드 생성과 관련된 경고 및 오류를 식별하도록 하려면 averagingFilterCG%#codegen 지시문을 추가합니다. 코드 생성 시 입력 변수 유형을 정의해야 합니다. 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;

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            : 24.1
 * C/C++ source code generated on  : 07-Mar-2024 13:15:05
 */

/* 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));
  i = y->size[0] * y->size[1];
  y->size[0] = 1;
  y->size[1] = x->size[1];
  emxEnsureCapacity_real_T(y, i);
  y_data = y->data;
  loop_ub = x->size[1];
  for (i = 0; i < loop_ub; i++) {
    y_data[i] = 0.0;
  }
  i = x->size[1];
  for (loop_ub = 0; loop_ub < i; loop_ub++) {
    double b_y;
    memcpy(&b_slider[0], &slider[0], 15U * sizeof(double));
    /*  move one position in the buffer */
    b_y = x_data[loop_ub];
    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[loop_ub] = 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            : 24.1
// C/C++ source code generated on  : 07-Mar-2024 13:15:09
//

// 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 i;
  int loop_ub;
  std::memset(&slider[0], 0, 16U * sizeof(double));
  y.set_size(1, x.size(1));
  loop_ub = x.size(1);
  for (i = 0; i < loop_ub; i++) {
    y[i] = 0.0;
  }
  i = x.size(1);
  for (loop_ub = 0; loop_ub < i; loop_ub++) {
    double b_y;
    std::copy(&slider[0], &slider[15], &b_slider[0]);
    //  move one position in the buffer
    b_y = x[loop_ub];
    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[loop_ub] = b_y / 16.0;
    //  write the average of the current window to y
  }
}

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