Этот пример показывает, как сгенерировать автономную библиотеку C из кода MATLAB, который читает файл из диска с помощью функций fopen/fread/fclose.
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
.
codegen readfile
Прежде, чем сгенерировать код С, необходимо сначала протестировать MEX-функцию в MATLAB, чтобы гарантировать, что это функционально эквивалентно оригинальному коду MATLAB и что никакие ошибки времени выполнения не происходят. По умолчанию codegen
генерирует MEX-функцию под названием readfile_mex
в текущей папке. Это позволяет вам тестировать код MATLAB и 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'
codegen -config:lib readfile
Используя codegen
с заданным -config cfg
опция производит автономную библиотеку C.
По умолчанию код, сгенерированный для библиотеки, находится в папке codegen/lib/readfile/
.
Файлы:
dir codegen/lib/readfile/
. readfile.c readfile_initialize.o .. readfile.h readfile_ref.rsp buildInfo.mat readfile.o readfile_rtw.mk codeInfo.mat readfile_data.c readfile_rtwutil.c codedescriptor.dmr readfile_data.h readfile_rtwutil.h examples readfile_data.o readfile_rtwutil.o fclose.c readfile_emxAPI.c readfile_terminate.c fclose.h readfile_emxAPI.h readfile_terminate.h fclose.o readfile_emxAPI.o readfile_terminate.o fileManager.c readfile_emxutil.c readfile_types.h fileManager.h readfile_emxutil.h rtw_proj.tmw fileManager.o readfile_emxutil.o rtwtypes.h interface readfile_initialize.c readfile.a readfile_initialize.h
readfile.c
type codegen/lib/readfile/readfile.c
/* * File: readfile.c * * MATLAB Coder version : 4.1 * C/C++ source code generated on : 21-Aug-2018 23:29:46 */ /* Include Files */ #include <string.h> #include "readfile.h" #include "readfile_emxutil.h" #include "fclose.h" #include "fileManager.h" #include "readfile_rtwutil.h" #include <stdio.h> /* Type Definitions */ #include <stddef.h> /* Function Definitions */ /* * 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) { signed char fileid; int wherefrom; FILE * filestar; long position_t; double position; int i0; unsigned char buffer[65536]; int remaining; int b_index; emxArray_uint16_T *r0; emxArray_uint8_T *A; boolean_T exitg1; int other2Read; size_t nBytes; int num2Read; int bytesOut; short bdims_idx_0; int numRead; int buf_size_idx_0; size_t numReadSizeT; char buf_data[1024]; /* 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, "rb"); /* Call fseek(f, 0, SEEK_END) to set file position to the end of */ /* the file. */ wherefrom = SEEK_END; filestar = fileManager(fileid); if ((fileid != 0) && (fileid != 1) && (fileid != 2)) { } else { filestar = NULL; } if (!(filestar == NULL)) { fseek(filestar, (long int)0.0, wherefrom); } /* Call ftell(f) which will return the length of the file in bytes */ /* (as current file position is at the end of the file). */ filestar = fileManager(fileid); if ((fileid != 0) && (fileid != 1) && (fileid != 2)) { } else { filestar = NULL; } if (filestar == NULL) { position = -1.0; } else { position_t = ftell(filestar); position = (double)position_t; } position = rt_roundd_snf(position); if (position < 2.147483648E+9) { if (position >= -2.147483648E+9) { i0 = (int)position; } else { i0 = MIN_int32_T; } } else if (position >= 2.147483648E+9) { i0 = MAX_int32_T; } else { i0 = 0; } /* Reset current file position */ wherefrom = SEEK_SET; filestar = fileManager(fileid); if ((fileid != 0) && (fileid != 1) && (fileid != 2)) { } else { filestar = NULL; } if (!(filestar == NULL)) { fseek(filestar, (long int)0.0, wherefrom); } /* Initialize a buffer */ memset(&buffer[0], 0, sizeof(unsigned char) << 16); /* Remaining is the number of bytes to read (from the file) */ remaining = i0; /* Index is the current position to read into the buffer */ b_index = 1; emxInit_uint16_T(&r0, 2); emxInit_uint8_T(&A, 1); exitg1 = false; while ((!exitg1) && (remaining > 0)) { /* Buffer overflow? */ if (b_index > MAX_int32_T - remaining) { other2Read = MAX_int32_T; } else { other2Read = remaining + b_index; } if (other2Read > 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, i0); fflush(stdout); exitg1 = true; } else { /* Read as much as possible from the file into internal buffer */ nBytes = sizeof(char); filestar = fileManager(fileid); if ((fileid != 0) && (fileid != 1) && (fileid != 2)) { } else { filestar = NULL; } if (filestar == NULL) { A->size[0] = 0; bytesOut = 0; } else { num2Read = A->size[0]; A->size[0] = remaining; emxEnsureCapacity_uint8_T(A, num2Read); if (remaining > 1024) { bdims_idx_0 = 1024; } else { bdims_idx_0 = (short)remaining; } bytesOut = 0; numRead = 1; buf_size_idx_0 = bdims_idx_0; while ((bytesOut < remaining) && (numRead > 0)) { num2Read = buf_size_idx_0; other2Read = remaining - bytesOut; if (buf_size_idx_0 > other2Read) { num2Read = other2Read; } buf_size_idx_0 = bdims_idx_0; numRead = 0; other2Read = 1; while ((numRead < num2Read) && (other2Read > 0)) { numReadSizeT = fread(&buf_data[numRead], nBytes, num2Read - numRead, filestar); other2Read = (int)numReadSizeT; numRead += (int)numReadSizeT; } for (other2Read = 0; other2Read < numRead; other2Read++) { A->data[other2Read + bytesOut] = (unsigned char)buf_data[other2Read]; } bytesOut += numRead; } num2Read = bytesOut + 1; buf_size_idx_0 = A->size[0]; for (other2Read = num2Read; other2Read <= buf_size_idx_0; other2Read++) { A->data[other2Read - 1] = 0U; } if (bytesOut < remaining) { if (1 > bytesOut) { A->size[0] = 0; } else { num2Read = A->size[0]; A->size[0] = bytesOut; emxEnsureCapacity_uint8_T(A, num2Read); } } } position = (double)b_index + (double)bytesOut; if (position < 2.147483648E+9) { if (position >= -2.147483648E+9) { num2Read = (int)position; } else { num2Read = MIN_int32_T; } } else { num2Read = MAX_int32_T; } num2Read--; if (b_index > num2Read) { buf_size_idx_0 = 0; num2Read = 0; } else { buf_size_idx_0 = b_index - 1; } other2Read = r0->size[0] * r0->size[1]; r0->size[0] = 1; numRead = num2Read - buf_size_idx_0; r0->size[1] = numRead; emxEnsureCapacity_uint16_T(r0, other2Read); for (num2Read = 0; num2Read < numRead; num2Read++) { r0->data[num2Read] = (unsigned short)(buf_size_idx_0 + num2Read); } numRead = r0->size[0] * r0->size[1]; for (num2Read = 0; num2Read < numRead; num2Read++) { buffer[r0->data[num2Read]] = A->data[num2Read]; } if (bytesOut == 0) { /* Nothing more to read */ exitg1 = true; } else { /* Did something went wrong when reading? */ if (bytesOut < 0) { printf("Could not read from file: %d.\n", bytesOut); fflush(stdout); exitg1 = true; } else { /* Update state variables */ remaining -= bytesOut; if ((b_index < 0) && (bytesOut < MIN_int32_T - b_index)) { b_index = MIN_int32_T; } else if ((b_index > 0) && (bytesOut > MAX_int32_T - b_index)) { b_index = MAX_int32_T; } else { b_index += bytesOut; } } } } } emxFree_uint8_T(&A); emxFree_uint16_T(&r0); /* Close file */ b_fclose(fileid); i0 = y->size[0] * y->size[1]; y->size[0] = 1; y->size[1] = b_index; emxEnsureCapacity_char_T(y, i0); for (i0 = 0; i0 < b_index; i0++) { y->data[i0] = (signed char)buffer[i0]; } } /* * File trailer for readfile.c * * [EOF] */