Generazione di codice C/C++ da una funzione di MATLAB
Questo esempio mostra il workflow consigliato per generare codice C/C++ da una funzione di MATLAB®. I passaggi di questo workflow sono:
Preparare il codice MATLAB per la generazione di codice.
Generare e testare la funzione MEX.
Generare ed esaminare il codice C/C++.
Questo esempio genera codice C/C++ dalla riga di comando utilizzando il comando codegen
. Per scoprire come generare codice utilizzando l'app MATLAB Coder™, vedere Generate C Code by Using the MATLAB Coder App.
Creazione del codice MATLAB e dei dati di campionamento
Questo passaggio è necessario ai fini dell'esempio e non è un passaggio tipico del workflow di generazione di codice.
Creare una funzione di MATLAB averagingFilterML
che agisca come filtro di media su un segnale di input. Questa funzione accetta un vettore di input dei valori del segnale e restituisce un vettore di output dei valori filtrati. Il vettore di output ha le stesse dimensioni del vettore di input. La funzione averagingFilterML
utilizza la variabile slider
per rappresentare una finestra scorrevole di 16 valori di segnale e calcola il valore medio del segnale per ciascuna posizione della finestra.
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
Generare un'onda sinusoidale rumorosa come dati di campionamento e utilizzare averagingFilterML
per filtrare i dati rumorosi. Tracciare i dati rumorosi e i dati filtrati nella stessa finestra grafica.
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;
Passaggio 1: preparare il codice MATLAB per la generazione di codice
Rinominare la funzione averagingFilterML
in averagingFilterCG
. Aggiungere la direttiva %#codegen
a averagingFilterCG
per indicare a MATLAB Code Analyzer di identificare gli avvisi e gli errori specifici della generazione di codice. Per la generazione di codice, è necessario definire i tipi delle variabili di input. Specificare l'input come vettore illimitato di doubles
utilizzando un blocco arguments
.
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
Passaggio 2: generare e testare la funzione MEX
È importante generare e testare una funzione MEX prima di generare codice C/C++. L'esecuzione della funzione MEX in MATLAB prima della generazione del codice C/C++ consente di rilevare e correggere errori di runtime che sono molto più difficili da diagnosticare nel codice generato. Inoltre, è possibile utilizzare la funzione MEX per verificare che il codice generato funzioni in modo analogo al codice MATLAB originale.
Utilizzare il comando codegen
per generare una funzione MEX da averagingFilterCG
. Testare la funzione MEX con lo stesso input passato alla funzione originale di MATLAB e confrontare i risultati. La funzione MEX produce lo stesso output.
codegen averagingFilterCG
Code generation successful.
z = averagingFilterCG_mex(x); plot(x,"red"); hold on plot(z,"blue"); hold off;
Passaggio 3: generare ed esaminare il codice C/C++
Utilizzare il comando codegen
con l'opzione -config:lib
per generare una libreria C autonoma. Esaminare la funzione averagingFilterCG
nel codice C generato.
codegen -config:lib averagingFilterCG
Code generation successful.
type(fullfile("codegen","lib","averagingFilterCG","averagingFilterCG.c"))
/* * Prerelease License - for engineering feedback and testing purposes * only. Not for sale. * File: averagingFilterCG.c * * MATLAB Coder version : 25.1 * C/C++ source code generated on : 01-Feb-2025 07:27:41 */ /* 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] */
In alternativa, utilizzare il comando codegen
con le opzioni -config:lib
e -lang:C++
per generare una libreria C++ autonoma. Confrontare la funzione averagingFilterCG
nel codice C++ generato con quella nel codice C generato.
codegen -config:lib -lang:c++ averagingFilterCG
Code generation successful.
type(fullfile("codegen","lib","averagingFilterCG","averagingFilterCG.cpp"))
// // Prerelease License - for engineering feedback and testing purposes // only. Not for sale. // File: averagingFilterCG.cpp // // MATLAB Coder version : 25.1 // C/C++ source code generated on : 01-Feb-2025 07:27:45 // // 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] //