Matlab Coder生成变长数组解析
一、主要代码分成三部分
以自定义函数 myrandi 作为示例,随机产生长度为L,[Min,Max]之间的整数值。
1. 初始化函数
/* Initialize the application.
You do not need to do this more than one time. */
myrandi_initialize();
函数的初始化,获取初始值。
2. 入口函数
/* Invoke the entry-point functions.
You can call entry-point functions multiple times. */
main_myrandi();
//进入点函数,只是代码的主要部分。
3. 中断退出函数
/* Terminate the application.
You do not need to do this more than one time. */
myrandi_terminate();
//函数结束,退出。
二、进入点函数关键点详解
1. 变长度数组对应的结构体
//数组对应的结构体,结构体对应的含义如解释所示
struct emxArray_real_T
{
double *data; //对应数组类型的指针(输出的结果数值)
int *size; //对应数组的尺度的指针
int allocatedSize; //分配的个数
int numDimensions; //对应数组的维度
boolean_T canFreeData; //typedef boolean_T bool,对应数组内存释放标志;
}; // typedef struct emxArray_real_T emxArray_real_T;
2. 结构体的初始化(只有一个维数输入)
// 结构体赋初值, emxInitArray_real_T 与 emxInit_real_T实现相同的功能
// 参数为结构体的二级指针(初始化后的数据存储在该结构体)和数组维数
// 实际的输入只有一个参数:int numDimensions;
// emxArray_real_T **pEmxArray为输出参数。
void emxInit_real_T(emxArray_real_T **pEmxArray, int numDimensions)
{
emxArray_real_T *emxArray;
int i;
*pEmxArray = (emxArray_real_T *)malloc(sizeof(emxArray_real_T));
emxArray = *pEmxArray;
emxArray->data = (double *)NULL;//该结构体数据指针赋初值为NULL
emxArray->numDimensions = numDimensions;//该结构体的维数
emxArray->size = (int *)malloc(sizeof(int) * numDimensions);//该结构体的大小内存分配
emxArray->allocatedSize = 0;//该结构体数据的个数
emxArray->canFreeData = true;//该结构体指针释放标志
for (i = 0; i < numDimensions; i++) {
emxArray->size[i] = 0;//该结构体的大小赋初值为0
}
}
3. 结构体的初始化(有两个参数的输入:维数和数据尺度)
// ND 获取N维的初始化结构体
// 实际有两个参数输入:int numDimensions, int *size。
// emxArray_real_T *emx为返回的结构体指针类型
emxArray_real_T *emxCreateND_real_T(int numDimensions, int *size)
{
emxArray_real_T *emx;
int numEl; // 元素的个数
int i;
emxInit_real_T(&emx, numDimensions);
numEl = 1;
for (i = 0; i < numDimensions; i++) {
numEl *= size[i];
emx->size[i] = size[i];// 由已知参数赋给对应的结构体
}
emx->data = (double *)calloc((unsigned int)numEl, sizeof(double));// 给数据指针分配大小并赋初值为 0
emx->numDimensions = numDimensions;
emx->allocatedSize = numEl;// 数据的个数赋给分配内存的个数,allocatedSize 应大于或等于numEl
return emx; // 返回该结构体指针
}
4. 结构体的初始化(有三个参数的输入:数据、维数和数据尺度)
// ND 获取N维的数据 并且有数据的初始化,即包装函数Wrapper(data获取数据,numEl 为数据元素的个数, 此时emx->canFreeData = false;)
emxArray_real_T *emxCreateWrapperND_real_T(double *data, int numDimensions, int *
size)
{
emxArray_real_T *emx;
int numEl;
int i;
emxInit_real_T(&emx, numDimensions);
numEl = 1;
for (i = 0; i < numDimensions; i++) {
numEl *= size[i];
emx->size[i] = size[i];
}
emx->data = data;// 给对应的数据指针赋值
emx->numDimensions = numDimensions;
emx->allocatedSize = numEl;
emx->canFreeData = false;
return emx;
}
5. 结构体的初始化(有三个参数的输入:数据、行数和列数)
//行列对应的维数为 2,size[0] = rows; size[1] = cols; Wrapper表示有数据指针输入,此时 emx->canFreeData = false;
emxArray_real_T *emxCreateWrapper_real_T(double *data, int rows, int cols)
{
emxArray_real_T *emx;
int size[2];
int numEl;
int i;
size[0] = rows;
size[1] = cols;
emxInit_real_T(&emx, 2);
numEl = 1;
for (i = 0; i < 2; i++) {
numEl *= size[i];
emx->size[i] = size[i];
}
emx->data = data;
emx->numDimensions = 2;
emx->allocatedSize = numEl;
emx->canFreeData = false;
return emx;
}
6. 结构体的初始化(有两个参数的输入:行数和列数)
//行列对应的维数为 2,size[0] = rows; size[1] = cols;
emxArray_real_T *emxCreate_real_T(int rows, int cols)
{
emxArray_real_T *emx;
int size[2];
int numEl;
int i;
size[0] = rows;
size[1] = cols;
emxInit_real_T(&emx, 2);
numEl = 1;
for (i = 0; i < 2; i++) {
numEl *= size[i];
emx->size[i] = size[i];
}
emx->data = (double *)calloc((unsigned int)numEl, sizeof(double));
emx->numDimensions = 2;
emx->allocatedSize = numEl;
return emx;
}
三、动态扩展内存
// 思想方法值得借鉴,考虑边界情况,主要获取数据指针变化和分配数据的大小,
// 原结构体中 emxArray->allocatedSize的数值不足以表示实际的数据大小
//(个数)修改了维数和size,引起数据个数变化为newNumel,
//其中分配内存数据的额大小emxArray->allocatedSize
//应大于或等于newNumel ,数据分配的空间也要重新分配
// 主要实现由于 size 的变化,导致数据指针分配内存的变化和设置的数据内存量值的变化
void emxEnsureCapacity_real_T(emxArray_real_T *emxArray, int oldNumel)
{
int newNumel;
int i;
void *newData;
if (oldNumel < 0) {
oldNumel = 0;
}// 如果原数据个数小于0,则设置为 0
newNumel = 1;// 获取新数据的个数
for (i = 0; i < emxArray->numDimensions; i++) {
newNumel *= emxArray->size[i];
}
// 如果实际新元素个数大于已分配内存数据的个数,则执行相关操作
if (newNumel > emxArray->allocatedSize) {
i = emxArray->allocatedSize;
if (i < 16) {
i = 16;
}
while (i < newNumel) {
if (i > 1073741823) {
i = MAX_int32_T;
} else {
i <<= 1;// 左移一位 实现倍增
}
}
newData = calloc((unsigned int)i, sizeof(double));
if (emxArray->data != NULL) {
memcpy(newData, (void *)emxArray->data, sizeof(double) * oldNumel);// 原数据拷贝到新数据位置
if (emxArray->canFreeData) {
free((void *)emxArray->data);// 释放原数据指针
}
}
emxArray->data = (double *)newData;
emxArray->allocatedSize = i; // 此时分配的数据内存个数i >= newNumel(实际数据个数)
emxArray->canFreeData = true;
}
}
四、函数大小端的判断
// 实现判断大小端
uint16_T one = 1U;// typedef uint16 uint16_T
enum {
LittleEndian,
BigEndian
} machByteOrder = (*((uint8_T *) &one) == 1U) ? LittleEndian : BigEndian;