텍스트 파일을 읽어오는 코드 생성하기
이 예제에서는 함수 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 readfile
Code 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] */