テキスト ファイルを読み取るコードの生成
この例では、関数 fopen/fread/fclose を使用してディスクからファイルを読み取る MATLAB® コードからスタンドアロン C ライブラリを生成する方法を示します。
関数 readfile について
関数 readfile.m は、入力としてファイル名 (またはパス) を取得し、ファイルの内容を含む文字列を返します。
type readfile% y = readfile(filename)
% Read file 'filename' and return a MATLAB string with the contents
% of the file.
function y = readfile(filename) %#codegen
% Put class and size constraints on function input.
assert(isa(filename, 'char'));
assert(size(filename, 1) == 1);
assert(size(filename, 2) <= 1024);
% Call fopen(filename 'r'), but we need to convert the MATLAB
% string into a C type string (which is the same string with the
% NUL (\0) string terminator).
f = fopen(filename, 'r');
% Call fseek(f, 0, SEEK_END) to set file position to the end of
% the file.
fseek(f, 0, 'eof');
% Call ftell(f) which will return the length of the file in bytes
% (as current file position is at the end of the file).
filelen = int32(ftell(f));
% Reset current file position
fseek(f,0,'bof');
% Initialize a buffer
maxBufferSize = int32(2^16);
buffer = zeros(1, maxBufferSize,'uint8');
% Remaining is the number of bytes to read (from the file)
remaining = filelen;
% Index is the current position to read into the buffer
index = int32(1);
while remaining > 0
% Buffer overflow?
if remaining + index > size(buffer,2)
fprintf('Attempt to read file which is bigger than internal buffer.\n');
fprintf('Current buffer size is %d bytes and file size is %d bytes.\n', maxBufferSize, filelen);
break
end
% Read as much as possible from the file into internal buffer
[dataRead, nread] = fread(f,remaining, 'char');
buffer(index:index+nread-1) = dataRead;
n = int32(nread);
if n == 0
% Nothing more to read
break;
end
% Did something went wrong when reading?
if n < 0
fprintf('Could not read from file: %d.\n', n);
break;
end
% Update state variables
remaining = remaining - n;
index = index + n;
end
% Close file
fclose(f);
y = char(buffer(1:index));
検定に使用する MEX 関数の生成
codegen コマンドを使用して MEX 関数を生成します。
codegen readfileCode generation successful.
C コードを生成する前に、MATLAB で MEX 関数をテストして、その関数が元の MATLAB コードと機能的に等価であることと実行時のエラーが発生しないことを確認しなければなりません。既定で、codegen は、現在のフォルダーに readfile_mex という名前の MEX 関数を生成します。これにより、MATLAB コードと MEX 関数をテストして結果を比較することができます。
MEX 関数の実行
生成された MEX 関数を呼び出し、返された文字列のサイズと最初の 100 文字を表示します。
y = readfile_mex('readfile.m');
size(y)ans = 1×2
1 1857
y(1:100)
ans =
'% y = readfile(filename)
% Read file 'filename' and return a MATLAB string with the contents
% of th'
C コードの生成
codegen -config:lib readfile
Code generation successful.
-config cfg オプションを指定して codegen を使用すると、スタンドアロン C ライブラリが生成されます。
生成されたコードの確認
既定では、ライブラリ用に生成されたコードは codegen/lib/readfile/ フォルダーにあります。
ファイルは、以下のとおりです。
dir codegen/lib/readfile/. .. _clang-format buildInfo.mat codeInfo.mat codedescriptor.dmr compileInfo.mat examples fileManager.c fileManager.h fileManager.o fread.c fread.h fread.o fseek.c fseek.h fseek.o ftell.c ftell.h ftell.o interface readfile.a readfile.c readfile.h readfile.o readfile_data.c readfile_data.h readfile_data.o readfile_emxAPI.c readfile_emxAPI.h readfile_emxAPI.o readfile_emxutil.c readfile_emxutil.h readfile_emxutil.o readfile_initialize.c readfile_initialize.h readfile_initialize.o readfile_rtw.mk readfile_terminate.c readfile_terminate.h readfile_terminate.o readfile_types.h rtw_proj.tmw rtwtypes.h
関数 readfile.c の C コードの検査
type codegen/lib/readfile/readfile.c/*
* File: readfile.c
*
* MATLAB Coder version : 25.1
* C/C++ source code generated on : 13-Jul-2025 16:33:12
*/
/* Include Files */
#include "readfile.h"
#include "fileManager.h"
#include "fread.h"
#include "fseek.h"
#include "ftell.h"
#include "readfile_data.h"
#include "readfile_emxutil.h"
#include "readfile_initialize.h"
#include "readfile_types.h"
#include <math.h>
#include <stdio.h>
#include <string.h>
/* Function Declarations */
static double rt_roundd_snf(double u);
/* Function Definitions */
/*
* Arguments : double u
* Return Type : double
*/
static double rt_roundd_snf(double u)
{
double y;
if (fabs(u) < 4.503599627370496E+15) {
if (u >= 0.5) {
y = floor(u + 0.5);
} else if (u > -0.5) {
y = u * 0.0;
} else {
y = ceil(u - 0.5);
}
} else {
y = u;
}
return y;
}
/*
* Put class and size constraints on function input.
*
* Arguments : const char filename_data[]
* const int filename_size[2]
* emxArray_char_T *y
* Return Type : void
*/
void readfile(const char filename_data[], const int filename_size[2],
emxArray_char_T *y)
{
emxArray_real_T *dataRead;
double d;
double *dataRead_data;
int b_index;
int i;
int i1;
int qY;
int remaining;
unsigned char buffer[65536];
signed char fileid;
char *y_data;
boolean_T exitg1;
if (!isInitialized_readfile) {
readfile_initialize();
}
/* y = readfile(filename) */
/* Read file 'filename' and return a MATLAB string with the contents */
/* of the file. */
/* Call fopen(filename 'r'), but we need to convert the MATLAB */
/* string into a C type string (which is the same string with the */
/* NUL (\0) string terminator). */
fileid = cfopen(filename_data, filename_size);
/* Call fseek(f, 0, SEEK_END) to set file position to the end of */
/* the file. */
b_fseek(fileid);
/* Call ftell(f) which will return the length of the file in bytes */
/* (as current file position is at the end of the file). */
d = rt_roundd_snf(b_ftell(fileid));
if (d < 2.147483648E+9) {
if (d >= -2.147483648E+9) {
i = (int)d;
} else {
i = MIN_int32_T;
}
} else if (d >= 2.147483648E+9) {
i = MAX_int32_T;
} else {
i = 0;
}
/* Reset current file position */
c_fseek(fileid);
/* Initialize a buffer */
memset(&buffer[0], 0, 65536U * sizeof(unsigned char));
/* Remaining is the number of bytes to read (from the file) */
remaining = i;
/* Index is the current position to read into the buffer */
b_index = 1;
emxInit_real_T(&dataRead);
exitg1 = false;
while ((!exitg1) && (remaining > 0)) {
/* Buffer overflow? */
if (b_index > MAX_int32_T - remaining) {
qY = MAX_int32_T;
} else {
qY = remaining + b_index;
}
if (qY > 65536) {
printf("Attempt to read file which is bigger than internal buffer.\n");
fflush(stdout);
printf("Current buffer size is %d bytes and file size is %d bytes.\n",
65536, i);
fflush(stdout);
exitg1 = true;
} else {
double nread;
int i2;
/* Read as much as possible from the file into internal buffer */
nread = b_fread(fileid, remaining, dataRead);
dataRead_data = dataRead->data;
d = rt_roundd_snf((double)b_index + nread);
if (d < 2.147483648E+9) {
if (d >= -2.147483648E+9) {
qY = (int)d;
} else {
qY = MIN_int32_T;
}
} else if (d >= 2.147483648E+9) {
qY = MAX_int32_T;
} else {
qY = 0;
}
if (qY < -2147483647) {
qY = MIN_int32_T;
} else {
qY--;
}
if (b_index > qY) {
i2 = 0;
qY = 0;
} else {
i2 = b_index - 1;
}
qY -= i2;
for (i1 = 0; i1 < qY; i1++) {
unsigned char u;
d = rt_roundd_snf(dataRead_data[i1]);
if (d < 256.0) {
if (d >= 0.0) {
u = (unsigned char)d;
} else {
u = 0U;
}
} else if (d >= 256.0) {
u = MAX_uint8_T;
} else {
u = 0U;
}
buffer[i2 + i1] = u;
}
d = rt_roundd_snf(nread);
if (d < 2.147483648E+9) {
if (d >= -2.147483648E+9) {
qY = (int)d;
} else {
qY = MIN_int32_T;
}
} else if (d >= 2.147483648E+9) {
qY = MAX_int32_T;
} else {
qY = 0;
}
if (qY == 0) {
/* Nothing more to read */
exitg1 = true;
/* Did something went wrong when reading? */
} else if (qY < 0) {
printf("Could not read from file: %d.\n", qY);
fflush(stdout);
exitg1 = true;
} else {
/* Update state variables */
remaining -= qY;
if ((b_index < 0) && (qY < MIN_int32_T - b_index)) {
b_index = MIN_int32_T;
} else if ((b_index > 0) && (qY > MAX_int32_T - b_index)) {
b_index = MAX_int32_T;
} else {
b_index += qY;
}
}
}
}
emxFree_real_T(&dataRead);
/* Close file */
cfclose(fileid);
qY = y->size[0] * y->size[1];
y->size[0] = 1;
y->size[1] = b_index;
emxEnsureCapacity_char_T(y, qY);
y_data = y->data;
for (i1 = 0; i1 < b_index; i1++) {
y_data[i1] = (signed char)buffer[i1];
}
}
/*
* File trailer for readfile.c
*
* [EOF]
*/