This example shows how to generate a standalone C library from MATLAB® code that reads a file from disk using the functions fopen/fread/fclose.
readfile FunctionThe readfile.m function takes a file name (or path) as input and returns a string containing the contents of the file.
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));
Generate a MEX function using the codegen command.
codegen readfileCode generation successful.
Before generating C code, you should first test the MEX function in MATLAB to ensure that it is functionally equivalent to the original MATLAB code and that no run-time errors occur. By default, codegen generates a MEX function named readfile_mex in the current folder. This allows you to test the MATLAB code and MEX function and compare the results.
Call the generated MEX function and display the size of the returned string and its first 100 characters.
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
Code generation successful.
Using codegen with the specified -config cfg option produces a standalone C library.
By default, the code generated for the library is in the folder codegen/lib/readfile/.
The files are:
dir codegen/lib/readfile/. readfile.a readfile_initialize.h .. readfile.c readfile_initialize.o .gitignore readfile.h readfile_rtw.mk _clang-format readfile.o readfile_rtwutil.c buildInfo.mat readfile_data.c readfile_rtwutil.h codeInfo.mat readfile_data.h readfile_rtwutil.o codedescriptor.dmr readfile_data.o readfile_terminate.c compileInfo.mat readfile_emxAPI.c readfile_terminate.h defines.txt readfile_emxAPI.h readfile_terminate.o examples readfile_emxAPI.o readfile_types.h fileManager.c readfile_emxutil.c rtw_proj.tmw fileManager.h readfile_emxutil.h rtwtypes.h fileManager.o readfile_emxutil.o interface readfile_initialize.c
readfile.c Functiontype codegen/lib/readfile/readfile.c/*
* File: readfile.c
*
* MATLAB Coder version : 5.2
* C/C++ source code generated on : 21-Feb-2023 13:14:28
*/
/* Include Files */
#include "readfile.h"
#include "fileManager.h"
#include "readfile_data.h"
#include "readfile_emxutil.h"
#include "readfile_initialize.h"
#include "readfile_rtwutil.h"
#include "readfile_types.h"
#include <stddef.h>
#include <stdio.h>
#include <string.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)
{
FILE *filestar;
int wherefrom;
long position_t;
size_t nBytes;
size_t numReadSizeT;
emxArray_uint8_T *At;
emxArray_uint8_T *b_At;
double position;
int b_index;
int bytesOut;
int c;
int dims_idx_0;
int i;
int i1;
int numRead;
int other2Read;
int remaining;
short bdims_idx_0;
unsigned char buffer[65536];
char tbuf[1024];
signed char fileid;
boolean_T doEOF;
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, "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)) {
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)) {
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) {
i = (int)position;
} else {
i = MIN_int32_T;
}
} else if (position >= 2.147483648E+9) {
i = MAX_int32_T;
} else {
i = 0;
}
/* Reset current file position */
wherefrom = SEEK_SET;
filestar = fileManager(fileid);
if ((fileid == 0) || (fileid == 1) || (fileid == 2)) {
filestar = NULL;
}
if (!(filestar == NULL)) {
fseek(filestar, (long int)0.0, wherefrom);
}
/* 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_uint8_T(&At, 2);
emxInit_uint8_T(&b_At, 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, i);
fflush(stdout);
exitg1 = true;
} else {
/* Read as much as possible from the file into internal buffer */
if (remaining >= MAX_int32_T) {
dims_idx_0 = 1024;
doEOF = true;
} else {
dims_idx_0 = remaining;
doEOF = false;
}
nBytes = sizeof(char);
filestar = fileManager(fileid);
if ((fileid == 0) || (fileid == 1) || (fileid == 2)) {
filestar = NULL;
}
if (!doEOF) {
if (filestar == NULL) {
b_At->size[0] = 0;
bytesOut = 0;
} else {
i1 = b_At->size[0];
b_At->size[0] = remaining;
emxEnsureCapacity_uint8_T(b_At, i1);
if (dims_idx_0 > 1024) {
bdims_idx_0 = 1024;
} else {
bdims_idx_0 = (short)dims_idx_0;
}
bytesOut = 0;
numRead = 1;
while ((bytesOut < dims_idx_0) && (numRead > 0)) {
c = bdims_idx_0;
other2Read = dims_idx_0 - bytesOut;
if (bdims_idx_0 > other2Read) {
c = other2Read;
}
numRead = 0;
other2Read = 1;
while ((numRead < c) && (other2Read > 0)) {
numReadSizeT =
fread(&tbuf[numRead], nBytes, c - numRead, filestar);
other2Read = (int)numReadSizeT;
numRead += (int)numReadSizeT;
}
for (c = 0; c < numRead; c++) {
b_At->data[c + bytesOut] = (unsigned char)tbuf[c];
}
bytesOut += numRead;
}
i1 = bytesOut + 1;
other2Read = b_At->size[0];
for (c = i1; c <= other2Read; c++) {
b_At->data[c - 1] = 0U;
}
if (bytesOut < remaining) {
i1 = b_At->size[0];
if (1 > bytesOut) {
b_At->size[0] = 0;
} else {
b_At->size[0] = bytesOut;
}
emxEnsureCapacity_uint8_T(b_At, i1);
}
}
} else {
At->size[0] = 0;
At->size[1] = 1;
if (filestar == NULL) {
bytesOut = 0;
} else {
c = 1;
bytesOut = 0;
while (c > 0) {
c = 0;
numRead = 1;
while ((c < 1024) && (numRead > 0)) {
numReadSizeT = fread(&tbuf[c], nBytes, 1024 - c, filestar);
numRead = (int)numReadSizeT;
c += (int)numReadSizeT;
}
if (1 > c) {
numRead = 0;
} else {
numRead = c;
}
i1 = b_At->size[0];
b_At->size[0] = At->size[0] + numRead;
emxEnsureCapacity_uint8_T(b_At, i1);
other2Read = At->size[0];
for (i1 = 0; i1 < other2Read; i1++) {
b_At->data[i1] = At->data[i1];
}
for (i1 = 0; i1 < numRead; i1++) {
b_At->data[i1 + At->size[0]] = (unsigned char)tbuf[i1];
}
i1 = At->size[0] * At->size[1];
At->size[0] = b_At->size[0];
At->size[1] = 1;
emxEnsureCapacity_uint8_T(At, i1);
numRead = b_At->size[0];
for (i1 = 0; i1 < numRead; i1++) {
At->data[i1] = b_At->data[i1];
}
bytesOut += c;
}
}
i1 = b_At->size[0];
b_At->size[0] = At->size[0];
emxEnsureCapacity_uint8_T(b_At, i1);
numRead = At->size[0];
for (i1 = 0; i1 < numRead; i1++) {
b_At->data[i1] = At->data[i1];
}
}
position = (double)b_index + (double)bytesOut;
if (position < 2.147483648E+9) {
if (position >= -2.147483648E+9) {
i1 = (int)position;
} else {
i1 = MIN_int32_T;
}
} else {
i1 = MAX_int32_T;
}
if (b_index > i1 - 1) {
other2Read = -1;
i1 = -1;
} else {
other2Read = b_index - 2;
i1 -= 2;
}
numRead = i1 - other2Read;
for (i1 = 0; i1 < numRead; i1++) {
buffer[(other2Read + i1) + 1] = b_At->data[i1];
}
if (bytesOut == 0) {
/* Nothing more to read */
exitg1 = true;
/* Did something went wrong when reading? */
} else 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(&b_At);
emxFree_uint8_T(&At);
/* Close file */
cfclose(fileid);
i = y->size[0] * y->size[1];
y->size[0] = 1;
y->size[1] = b_index;
emxEnsureCapacity_char_T(y, i);
for (i = 0; i < b_index; i++) {
y->data[i] = (signed char)buffer[i];
}
}
/*
* File trailer for readfile.c
*
* [EOF]
*/