Matlab Coder生成代码解析

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;
  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值