В этом примере показано, как сгенерировать автономную библиотеку 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 readfileCode generation successful.
Прежде, чем сгенерировать код С, необходимо сначала протестировать 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
Code generation successful.
Используя codegen с заданным -config cfg опция производит автономную библиотеку C.
По умолчанию код, сгенерированный для библиотеки, находится в папке codegen/lib/readfile/.
Файлы:
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 Функцияtype codegen/lib/readfile/readfile.c/*
* File: readfile.c
*
* MATLAB Coder version : 5.2
* C/C++ source code generated on : 21-Apr-2021 01:24:57
*/
/* 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 i;
int num2Read;
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) {
c = 1024;
doEOF = true;
} else {
c = 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 {
numRead = b_At->size[0];
b_At->size[0] = remaining;
emxEnsureCapacity_uint8_T(b_At, numRead);
if (c > 1024) {
bdims_idx_0 = 1024;
} else {
bdims_idx_0 = (short)c;
}
bytesOut = 0;
numRead = 1;
while ((bytesOut < c) && (numRead > 0)) {
num2Read = bdims_idx_0;
other2Read = c - bytesOut;
if (bdims_idx_0 > other2Read) {
num2Read = other2Read;
}
numRead = 0;
other2Read = 1;
while ((numRead < num2Read) && (other2Read > 0)) {
numReadSizeT =
fread(&tbuf[numRead], nBytes, num2Read - numRead, filestar);
other2Read = (int)numReadSizeT;
numRead += (int)numReadSizeT;
}
for (other2Read = 0; other2Read < numRead; other2Read++) {
b_At->data[other2Read + bytesOut] =
(unsigned char)tbuf[other2Read];
}
bytesOut += numRead;
}
numRead = bytesOut + 1;
num2Read = b_At->size[0];
for (other2Read = numRead; other2Read <= num2Read; other2Read++) {
b_At->data[other2Read - 1] = 0U;
}
if (bytesOut < remaining) {
numRead = b_At->size[0];
if (1 > bytesOut) {
b_At->size[0] = 0;
} else {
b_At->size[0] = bytesOut;
}
emxEnsureCapacity_uint8_T(b_At, numRead);
}
}
} 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) {
other2Read = 0;
} else {
other2Read = c;
}
numRead = b_At->size[0];
b_At->size[0] = At->size[0] + other2Read;
emxEnsureCapacity_uint8_T(b_At, numRead);
num2Read = At->size[0];
for (numRead = 0; numRead < num2Read; numRead++) {
b_At->data[numRead] = At->data[numRead];
}
for (numRead = 0; numRead < other2Read; numRead++) {
b_At->data[numRead + At->size[0]] = (unsigned char)tbuf[numRead];
}
numRead = At->size[0] * At->size[1];
At->size[0] = b_At->size[0];
At->size[1] = 1;
emxEnsureCapacity_uint8_T(At, numRead);
other2Read = b_At->size[0];
for (numRead = 0; numRead < other2Read; numRead++) {
At->data[numRead] = b_At->data[numRead];
}
bytesOut += c;
}
}
numRead = b_At->size[0];
b_At->size[0] = At->size[0];
emxEnsureCapacity_uint8_T(b_At, numRead);
other2Read = At->size[0];
for (numRead = 0; numRead < other2Read; numRead++) {
b_At->data[numRead] = At->data[numRead];
}
}
position = (double)b_index + (double)bytesOut;
if (position < 2.147483648E+9) {
if (position >= -2.147483648E+9) {
numRead = (int)position;
} else {
numRead = MIN_int32_T;
}
} else {
numRead = MAX_int32_T;
}
if (b_index > numRead - 1) {
num2Read = -1;
numRead = -1;
} else {
num2Read = b_index - 2;
numRead -= 2;
}
other2Read = numRead - num2Read;
for (numRead = 0; numRead < other2Read; numRead++) {
buffer[(num2Read + numRead) + 1] = b_At->data[numRead];
}
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]
*/