1)NDArray头文件:
- #ifndef NDArray_H
- #define NDArray_H
-
- #include
-
- #include
- #include
- #include
-
- #include "NDAttribute.h"
- #include "NDAttributeList.h"
- #include "Codec.h"
-
- /** NDArray中维度的最大数目 */
- #define ND_ARRAY_MAX_DIMS 10
-
- /** NDArray属性"colorMode"的颜色模式枚举 */
- typedef enum
- {
- NDColorModeMono, /**< 单色 */
- NDColorModeBayer, /**< Bayer模式图, 每个像素1个值,但在探测器上带有颜色过滤 */
- NDColorModeRGB1, /**< 像素颜色交错的RGB图像, 数据数组是[3, NX, NY] */
- NDColorModeRGB2, /**< 行颜色交错的RGB图像 , 数据数组是[NX, 3, NY] */
- NDColorModeRGB3, /**< 面颜色交错的RGB图像 , 数据数组是[NX, NY, 3] */
- NDColorModeYUV444, /**< YUV 图像, 3字节编码1个RGB像素 */
- NDColorModeYUV422, /**< YUV 图像, 4字节编码2个RGB像素 */
- NDColorModeYUV411 /**< YUV 图像, 6字节编码4个RGB像素 */
- } NDColorMode_t;
-
- /** NDArray属性"bayerPattern"的Bayer颜色枚举. 这个值仅对colorMode是NDColorModeBayer才有意义,
- * 因为在读出一个芯片子集时,Bayer模式将变化,所以需要这个值,例如如果X或Y偏移值不是偶数。
- */
- typedef enum
- {
- NDBayerRGGB = 0, /**< 第一行RGRG, 第二行GBGB... */
- NDBayerGBRG = 1, /**< 第一行GBGB, 第二行RGRG... */
- NDBayerGRBG = 2, /**< 第一行GRGR, 第二行BGBG... */
- NDBayerBGGR = 3 /**< 第一行BGBG, 第二行GRGR... */
- } NDBayerPattern_t;
-
- /** 定义一个NDArray维度的结构体 */
- typedef struct NDDimension {
- size_t size; /**< 数组的这个维度中元素数目 */
- size_t offset; /**< 相对于原始的数据来源(例如,探测器)的原点的偏移量。
- * 如果探测器的一个选取区域被读取,则这个值可以大于0.
- * 在unbinned像素中和默认方向,非反向中指定这个偏移值,
- * 偏移值是累积的,因此如果一个诸如NDPluginROI的插件进一步选取了一个子区域,
- * 这个偏移量是相对于探测器中第一个元素,而不是相对于传递给NDPluginROI的区域的第一个元素。
- */
- int binning; /**< binning(像素求和,1=no binning)相对于原始的数据来源(例如,探测器)
- * 偏移值是累积的,因而如果一个诸如NDPluginROI的插件执行binning,
- * 相对于探测器中像素而不是相对于传递给NDPluginROI的可能的binned像素表达这个binning。
- */
- int reverse; /**< 相对于原先的数据来源(例如,探测器)的方向(0=normal,1=reversed)
- * 这个值是累积的,因此如果一个诸如NDPluginROI的插件反向这些数据,值必须反映相对于原先探测器的方向,
- * 而不是相对于传递给NDPluginROI的可能的反向数据。
- */
- } NDDimension_t;
-
- /** 由NDArray::getInfo返回的结构体 */
- typedef struct NDArrayInfo {
- size_t nElements; /**< 数组中元素的总数 */
- int bytesPerElement; /**< 数组中每个元素的字节数*/
- size_t totalBytes; /**< 保存这个数组所需的字节总数;这可以小于NDArray::dataSize */
- /**< 以下对彩色图(RGB1,RGB2,RGB3)最有用 */
- NDColorMode_t colorMode; /**< 颜色模式 */
- int xDim; /**< 数组索引,它是X维度 */
- int yDim; /**< 数组索引,它是Y维度 */
- int colorDim; /**< 数组索引,它是颜色维度 */
- size_t xSize; /**< 这个数组的X尺寸 */
- size_t ySize; /**< 这个数组的Y尺寸 */
- size_t colorSize; /**< 这个数组的颜色尺寸 */
- size_t xStride; /**< X值之间数组元素的数目 */
- size_t yStride; /**< Y值之间数组元素的数目*/
- size_t colorStride; /**< 颜色值间数组元素的数目 */
- } NDArrayInfo_t;
-
- /**
- * N维度数组类;每个数组有一个维度,数据类型,数据指针以及可选的属性的集合。
- * 一个数组也有一个标识自身的uniqueId和timeStamp。NDArray对象可以由一个NDArrayPool对象分配,
- * 出于内存管理,NDArrayPool对象维护一个NDArrays的空闲列表。
- *
- */
- class ADCORE_API NDArray {
- public:
- /* 方向 */
- NDArray();
- NDArray(int ndims, size_t *dims, NDDataType_t dataType, size_t dataSize, void *pData);
- virtual ~NDArray();
- int initDimension (NDDimension_t *pDimension, size_t size);
- static int computeArrayInfo(int ndims, size_t *dims, NDDataType_t dataType, NDArrayInfo *pInfo);
- int getInfo (NDArrayInfo_t *pInfo);
- int reserve();
- int release();
- int getReferenceCount() const {return referenceCount;}
- int report(FILE *fp, int details);
- friend class NDArrayPool;
-
- private:
- ELLNODE node; /**< 这必须首先出现,因为ELLNODE必须与NDArray对象有相同地址 */
- int referenceCount; /**< 这个NDArray的引用计数,等于正在使用它的客户端数目 */
-
- public:
- class NDArrayPool *pNDArrayPool; /**< 创建这个数组的NDArrayPool对象 */
- class asynNDArrayDriver *pDriver; /**< 创建这个数组的asynNDArrayDriver*/
- int uniqueId; /**< 在一个驱动启动后,由它产生的所有NDArrays中一个必须唯一的编号。*/
- double timeStamp; /**< 这个数组以秒为单位的时间戳;推荐从EPICS纪元(00:00:00 UTC, January 1, 1990)的秒数
- 但某些驱动可以使用一个不同的起始的时间。*/
- epicsTimeStamp epicsTS; /**< epicsTimeStamp,用pasynManager->updateTimeStamp()设置这个变量,并且
- 可以来自一个用户定义的时间戳源。 */
- int ndims; /**< 这个数组中维度数目,最小=1 */
- NDDimension_t dims[ND_ARRAY_MAX_DIMS]; /**< 这个数组的维度尺寸的数组;前ndims个值是有意义 */
- NDDataType_t dataType; /**< 这个数组的数据类型 */
- size_t dataSize; /**< 这个数组的数据尺寸;为*pData分配的实际内存量,可以多于保存这个数组所需的内存量 */
- void *pData; /**< 指向数组数据的指针,认为按dims[0]变化最快,
- dims[ndims-1]变化最慢的顺序存储这些数据。 */
- NDAttributeList *pAttributeList; /**< 属性的链表 */
- Codec_t codec; /**< 用于压缩这些数据的codec定义. */
- size_t compressedSize; /**< 压缩数据的尺寸。如果pData未被压缩,应该与dataSize相等。*/
- };
-
- /*
- 这个类定义了一个被包含在std::multilist中的对象,std::multilist用于排序这个freeList_中的NDArrays
- 它定义了一个<操作符,用于使用NDArray::dataSize作为排序键。
- 我们想要在NDArrayPool.cpp中隐藏这个类,并且只是在这里先引用了它。
- //class sortedListElement;
-
- */
- class freeListElement {
- public:
- freeListElement(NDArray *pArray, size_t dataSize) {
- pArray_ = pArray;
- dataSize_ = dataSize;}
- friend bool operator<(const freeListElement& lhs, const freeListElement& rhs) {
- return (lhs.dataSize_ < rhs.dataSize_);
- }
- NDArray *pArray_;
- size_t dataSize_;
- private:
- freeListElement(); // 默认构造器是私有的,因而对象不能被无参构建
- };
-
- /**
- * NDArrayPool对象维护一个NDArrays的空闲列表(池)。驱动程序从这个池分配NDArray对象,并且传递这些对象给插件。
- * 当插件放置这个NDArray对象到它们的队列时,它们增加对这个对象的索引,而在它们处理完这个数组后,
- * 减少对这个对象的索引。当索引计数再次到达0时,这个NDArray对象被放回到空闲列表。
- * 这种机制使得在插件中数组的复制最小化。
- */
- class ADCORE_API NDArrayPool {
- public:
- NDArrayPool (class asynNDArrayDriver *pDriver, size_t maxMemory);
- virtual ~NDArrayPool() {}
- NDArray* alloc(int ndims, size_t *dims, NDDataType_t dataType, size_t dataSize, void *pData);
- NDArray* copy(NDArray *pIn, NDArray *pOut, bool copyData, bool copyDimensions=true, bool copyDataType=true);
-
- int reserve(NDArray *pArray);
- int release(NDArray *pArray);
- int convert(NDArray *pIn,
- NDArray **ppOut,
- NDDataType_t dataTypeOut,
- NDDimension_t *outDims);
- int convert(NDArray *pIn,
- NDArray **ppOut,
- NDDataType_t dataTypeOut);
- int report(FILE *fp, int details);
- int getNumBuffers();
- size_t getMaxMemory();
- size_t getMemorySize();
- int getNumFree();
- void emptyFreeList();
-
- protected:
- /**
- * 应该由管理派生自NDArray类的对象的池类,实现以下方法。
- */
- virtual NDArray* createArray();
- virtual void onAllocateArray(NDArray *pArray);
- virtual void onReserveArray(NDArray *pArray);
- virtual void onReleaseArray(NDArray *pArray);
-
- private:
- std::multiset
freeList_; - epicsMutexId listLock_; /**< 保护这个空闲列表 */
- int numBuffers_;
- size_t maxMemory_; /**< 允许这个对象分配的最大内存字节量; -1=无限*/
- size_t memorySize_; /**< 这个对象当前已经分配的内存字节量 */
- class asynNDArrayDriver *pDriver_; /**< 创建这个对象的asynNDArrayDriver */
- };
-
- #endif
2)NDArray的实现源文件:
- #include
- #include
- #include
- #include
-
- #include
- #include
-
- #include "NDArray.h"
-
- /** NDArray constructor, no parameters. NDArray构造器,不带参数。
- * 初始化所有字段为0,创建属性链表和链表互斥锁。
- */
- NDArray::NDArray() // referenceCount,pNDArrayPool,pDriver, uniqueId,timeStamp,ndims, dataType(NDInt8),pData
- : referenceCount(0), pNDArrayPool(0), pDriver(0),
- uniqueId(0), timeStamp(0.0), ndims(0), dataType(NDInt8),
- dataSize(0), pData(0)
- {
- this->epicsTS.secPastEpoch = 0;
- this->epicsTS.nsec = 0;
- memset(this->dims, 0, sizeof(this->dims)); // dims这个数组中元素全部填0
- memset(&this->node, 0, sizeof(this->node)); // ELLNODE node成员结构体填0
- this->pAttributeList = new NDAttributeList(); // 一个空的属性链表
- }
-
- NDArray::NDArray(int nDims, size_t *dims, NDDataType_t dataType, size_t dataSize, void *pData)
- : referenceCount(0), pNDArrayPool(0), pDriver(0),
- uniqueId(0), timeStamp(0.0), ndims(nDims), dataType(dataType), // 设置维度数目,每个维度上元素数目,数据类型,数据尺寸未传入值
- dataSize(dataSize), pData(0)
- {
- static const char *functionName = "NDArray::NDArray";
- this->epicsTS.secPastEpoch = 0;
- this->epicsTS.nsec = 0;
- this->pAttributeList = new NDAttributeList();
- this->referenceCount = 1;
-
- memset(this->dims, 0, sizeof(this->dims));
- for (int i=0; i
- this->dims[i].size = dims[i]; // 每一个维度上元素数目
- this->dims[i].offset = 0;
- this->dims[i].binning = 1;
- this->dims[i].reverse = 0;
- }
- NDArrayInfo arrayInfo;
- this->getInfo(&arrayInfo); // 获取数组信息
- //如果传入dataSize为0,则根据维度数目,每一维度上的元素数目,以及元素类型计算数据尺寸
- if (dataSize == 0) dataSize = arrayInfo.totalBytes;
- //
- if (arrayInfo.totalBytes > dataSize) {
- printf("%s: ERROR: required size=%d passed size=%d is too small\n",
- functionName, (int)arrayInfo.totalBytes, (int)dataSize);
- }
- /* 如果调用这传递了一个有效的缓存,使用这个缓存,相信它的尺寸是正确的 */
- if (pData) {
- this->pData = pData;
- } else {// 如果传递了一个NULL,则分配这个内存空间
- this->pData = malloc(dataSize);
- this->dataSize = dataSize;
- }
- }
-
- /** NDArray析构器
- * 释放这个数据数组,删除所有属性,释放属性列表并且销毁互斥量
- */
- NDArray::~NDArray()
- {
- if (this->pData) free(this->pData);
- delete this->pAttributeList;
- }
-
- /*
- * 便捷方法计算数组中总字节数
- typedef struct NDArrayInfo {
- size_t nElements; //总元素数目
- int bytesPerElement; //每个元素所用字节
- size_t totalBytes; //总字节数目
-
- NDColorMode_t colorMode;
- int xDim;
- int yDim;
- int colorDim;
- size_t xSize;
- size_t ySize;
- size_t colorSize;
- size_t xStride;
- size_t yStride;
- size_t colorStride;
- } NDArrayInfo_t;
- // 根据元素数据类型,维度数目和每一个维度上元素数目
- // 获取每个元素字节数,元素总数以及总字节数信息,存入NDArrayInfo结构体
- */
- int NDArray::computeArrayInfo(int ndims, size_t *dims, NDDataType_t dataType, NDArrayInfo *pInfo)
- {
- switch(dataType) // 根据指定的元素数据类型,计算每个元素需要的字节数
- case NDInt8:
- pInfo->bytesPerElement = sizeof(epicsInt8);
- break;
- case NDUInt8:
- pInfo->bytesPerElement = sizeof(epicsUInt8);
- break;
- case NDInt16:
- pInfo->bytesPerElement = sizeof(epicsInt16);
- break;
- case NDUInt16:
- pInfo->bytesPerElement = sizeof(epicsUInt16);
- break;
- case NDInt32:
- pInfo->bytesPerElement = sizeof(epicsInt32);
- break;
- case NDUInt32:
- pInfo->bytesPerElement = sizeof(epicsUInt32);
- break;
- case NDInt64:
- pInfo->bytesPerElement = sizeof(epicsInt64);
- break;
- case NDUInt64:
- pInfo->bytesPerElement = sizeof(epicsUInt64);
- break;
- case NDFloat32:
- pInfo->bytesPerElement = sizeof(epicsFloat32);
- break;
- case NDFloat64:
- pInfo->bytesPerElement = sizeof(epicsFloat64);
- break;
- default:
- return(ND_ERROR);
- break;
- }
- pInfo->nElements = 1;
- for (int i=0; i
nElements *= dims[i]; // 根据维度数目,每个维度上元素数目,计算总元素数目 - pInfo->totalBytes = pInfo->nElements * pInfo->bytesPerElement; // 根据每个元素所用字节数和总元素数目计算总字节数目
- return ND_SUCCESS;
- }
- /** 便捷方法:返回有关NDArray的信息;包括这个数组中元素数目,每个元素的字节数目,以及字节总数。
- [out] pInfo : 指向一个NDArrayInfo_t结构体的指针,必须已经由调用者分配 .
- */
- int NDArray::getInfo(NDArrayInfo_t *pInfo)
- {
- int i;
- NDAttribute *pAttribute;
- size_t *dims_t = new size_t[this->ndims]; // 根据维度数目分配一个数组
- for (i=0; i<this->ndims; i++) dims_t[i] = this->dims[i].size; // 数组中每个元素获取这个NDArray对象中每个维度的尺寸
- // 获取每个元素字节数,元素总数以及总字节数信息,存入NDArrayInfo结构体
- int status = NDArray::computeArrayInfo(this->ndims, dims_t, this->dataType, pInfo);
- delete[] dims_t;
- if (status != ND_SUCCESS) return status;
-
- pInfo->colorMode = NDColorModeMono; // 设置颜色模式为单色
- pAttribute = this->pAttributeList->find("ColorMode"); // 属性列表中能够找到颜色模式,则设置为获取到的颜色模式
- if (pAttribute) pAttribute->getValue(NDAttrInt32, &pInfo->colorMode);
- pInfo->xDim = 0;
- pInfo->yDim = 0;
- pInfo->colorDim = 0;
- pInfo->xSize = 0;
- pInfo->ySize = 0;
- pInfo->colorSize = 0;
- pInfo->xStride = 0;
- pInfo->yStride = 0;
- pInfo->colorStride = 0;
- if (this->ndims > 0) {
- pInfo->xStride = 1;// X方向是变化最快的维度
- pInfo->xSize = this->dims[0].size;
- }
- if (this->ndims > 1) {
- pInfo->yDim = 1; // Y方向是变化其次的维度
- pInfo->yStride = pInfo->xSize;
- pInfo->ySize = this->dims[1].size;
- }
- if (this->ndims == 3) {
- switch (pInfo->colorMode) {
- case NDColorModeRGB1:
- pInfo->xDim = 1;
- pInfo->yDim = 2;
- pInfo->colorDim = 0;
- pInfo->xStride = this->dims[0].size;
- pInfo->yStride = this->dims[0].size * this->dims[1].size;
- pInfo->colorStride = 1;
- break;
- case NDColorModeRGB2:
- pInfo->xDim = 0;
- pInfo->yDim = 2;
- pInfo->colorDim = 1;
- pInfo->xStride = 1;
- pInfo->yStride = this->dims[0].size * this->dims[1].size;
- pInfo->colorStride = this->dims[0].size;
- break;
- case NDColorModeRGB3:
- pInfo->xDim = 0;
- pInfo->yDim = 1;
- pInfo->colorDim = 2;
- pInfo->xStride = 1;
- pInfo->yStride = this->dims[0].size;
- pInfo->colorStride = this->dims[0].size * this->dims[1].size;
- break;
- default:
- // This is a 3-D array, but is not RGB
- pInfo->xDim = 0;
- pInfo->yDim = 1;
- pInfo->colorDim = 2;
- pInfo->xStride = 1;
- pInfo->yStride = this->dims[0].size;
- pInfo->colorStride = this->dims[0].size * this->dims[1].size;
- break;
- }
- pInfo->xSize = this->dims[pInfo->xDim].size; //xDim为0
- pInfo->ySize = this->dims[pInfo->yDim].size; //yDim为1
- pInfo->colorSize = this->dims[pInfo->colorDim].size;
- }
- return(ND_SUCCESS);
- }
-
- /*
- 初始化维度结构体NDDimension_t为size=size,binning=1,reverse=0,offset=0。
- [in] pDimension : 指向一个NDDimension_t结构体的指针,必须已经由调用者分配.
- */
- int NDArray::initDimension(NDDimension_t *pDimension, size_t size)
- {
- pDimension->size=size;
- pDimension->binning = 1;
- pDimension->offset = 0;
- pDimension->reverse = 0;
- return ND_SUCCESS;
- }
-
- /** 调用这个NDArray对象的NDArrayPool::reserve() ; 为这个数组增加引用计数 . */
- int NDArray::reserve()
- {
- const char *functionName = "NDArray::reserve";
-
- if (!pNDArrayPool) {
- printf("%s: WARNING, no owner\n", functionName);
- return(ND_ERROR);
- }
- return(pNDArrayPool->reserve(this));
- }
-
- /** 调用这个NDArray对象的NDArrayPool::reverse(); 减小这个数组的引用计数 . */
- int NDArray::release()
- {
- const char *functionName = "NDArray::release";
-
- if (!pNDArrayPool) {
- printf("%s: WARNING, no owner\n", functionName);
- return(ND_ERROR);
- }
- return(pNDArrayPool->release(this));
- }
-
- /** Reports on the properties of the array. 报告这个数组的性质。
- * [in] fp : 用于报告输出的文件指针.
- * [in] details: 所需报告详细程度;如果 >5,调用NDAttributeList::report().
- */
- int NDArray::report(FILE *fp, int details)
- {
- int dim;
-
- fprintf(fp, "\n");
- fprintf(fp, "NDArray Array address=%p:\n", this); // NDArray对象的地址
- fprintf(fp, " ndims=%d dims=[", this->ndims); // NDArray对象的维度数目
- for (dim=0; dim<this->ndims; dim++) fprintf(fp, "%d ", (int)this->dims[dim].size); // NDArray对象每个维度的元素数目
- fprintf(fp, "]\n");
- fprintf(fp, " dataType=%d, dataSize=%d, pData=%p\n", // 数据类型,数据尺寸,数据地址
- this->dataType, (int)this->dataSize, this->pData);
- fprintf(fp, " uniqueId=%d, timeStamp=%f, epicsTS.secPastEpoch=%d, epicsTS.nsec=%d\n", // 唯一id,时间戳
- this->uniqueId, this->timeStamp, this->epicsTS.secPastEpoch, this->epicsTS.nsec);
- fprintf(fp, " referenceCount=%d\n", this->referenceCount); // 引用计数
- fprintf(fp, " number of attributes=%d\n", this->pAttributeList->count()); // 属性数目
- if (details > 5) {
- this->pAttributeList->report(fp, details); // 每个属性信息
- }
- return ND_SUCCESS;
- }
3)测试代码:
- #include
- #include
- #include
- #include
- #include
-
- #include
- #include
- #include
- #include
- #include
-
- #include "NDArray.h"
-
- static asynUser * pasynUser = NULL;
-
- int main()
- {
- int nDims = 2;
- size_t dims[2];
- size_t dataSize = 0;
- epicsTimeStamp currentTime;
- //double timeStamp;
-
- dims[0] = 3; dims[1] = 5;
- epicsInt32 * pArrs = NULL;
-
- if (!pasynUser){
- pasynUser = pasynManager->createAsynUser(0,0);
- }
-
-
- //NDArray * pNDArray = new NDArray(int ndims, size_t *dims, NDDataType_t dataType, size_t dataSize, void *pData);
- NDArray * pNDArray = new NDArray(nDims, dims, NDInt32, dataSize, (void *)pArrs) ;
-
- // 获取数组数据的存储地址
- pArrs = (epicsInt32 *)pNDArray->pData;
-
- size_t i;
- size_t total = dims[0] * dims[1];
-
- // 对NDArray对象的数组赋值
- for (i = 0; i < total; i++){
- pArrs[i] = i;
- }
-
-
- // 更新timestamp时间戳
- pasynManager->updateTimeStamp(pasynUser);
- pNDArray->epicsTS = pasynUser->timestamp;
-
- // 更新以秒计的时间戳
- epicsTimeGetCurrent(¤tTime);
- pNDArray->timeStamp = currentTime.secPastEpoch + currentTime.nsec / 1.e9;
-
- // 调用NDArray对象的report方法 输出这个NDArray对象的信息
- pNDArray->report(stdout, 10);
- // 输出NDArray数组中的信息:
- size_t j;
- printf("array data Information:\n");
- for (i = 0; i < dims[1]; i++ ){
- for (j = 0; j < dims[0]; j++){
- printf("%u\t", pArrs[i * dims[0] + j]);
- }
- printf("\n");
- }
-
- NDArrayInfo_t info;
- pNDArray->getInfo(&info);
- printf("\n");
- printf("NDArrayInfo for the NDArray object:\n");
-
- /*
- * size_t nElements; //总元素数目
- int bytesPerElement; //每个元素所用字节
- size_t totalBytes; //总字节数目
- NDColorMode_t colorMode;
- int xDim;
- int yDim;
- int colorDim;
- size_t xSize;
- size_t ySize;
- size_t colorSize;
- size_t xStride;
- size_t yStride;
- size_t colorStride;
- * */
- printf("nElements: %lu,\tbytesPerElement:%d\ttotalBytes: %lu\n", info.nElements, info.bytesPerElement, info.totalBytes);
- printf("colorMode: %d\n", info.colorMode);
- printf("xDim:%d,\tyDim:%d,\tcolorDim:%d\n", info.xDim, info.yDim, info.colorDim);
- printf("xSize:%lu,\tySize:%lu,\tcolorSize:%lu\n", info.xSize, info.ySize, info.colorSize);
- printf("xStride:%lu\tyStride:%lu,\tcolorStride:%lu\n", info.xStride, info.yStride, info.colorStride);
-
- delete pNDArray;
-
- return 0;
- }
编译以上源文件进行测试,结果如下:
- root@orangepi5:/home/orangepi/C_program/host_program/hostApp# O.linux-aarch64/testNDArray
-
- NDArray Array address=0x55902dda30:
- ndims=2 dims=[3 5 ]
- dataType=4, dataSize=60, pData=0x55902ddc90
- uniqueId=0, timeStamp=1065510588.289565, epicsTS.secPastEpoch=0, epicsTS.nsec=0
- referenceCount=1
- number of attributes=0
-
- NDAttributeList: address=0x55902ddbd0:
- number of attributes=0
- array data Information:
- 0 1 2
- 3 4 5
- 6 7 8
- 9 10 11
- 12 13 14
-
- NDArrayInfo for the NDArray object:
- nElements: 15, bytesPerElement:4 totalBytes: 60
- colorMode: 0
- xDim:0, yDim:1, colorDim:0
- xSize:3, ySize:5, colorSize:0
- xStride:1 yStride:3, colorStride:0