MATLAB 的 mxGetFieldByNumber 和 mxGetFieldNameByNumber 返回不一致的结果
Posted
技术标签:
【中文标题】MATLAB 的 mxGetFieldByNumber 和 mxGetFieldNameByNumber 返回不一致的结果【英文标题】:MATLAB's mxGetFieldByNumber and mxGetFieldNameByNumber return incongruent results 【发布时间】:2021-10-09 03:03:38 【问题描述】:我有一个 C mex 例程,它在结构的子字段上进行迭代。有时,当 mxGetFieldNameByNumber() 返回相同字段 idx 的字符串时,调用 mxGetFieldByNumber() 返回 NULL。这是一个玩具:
numFields = getNumberOfFields( currentField );
for( fieldIdx = 0; fieldIdx < numFields; fieldIdx ++)
subField = mxGetFieldByNumber( currentField, 0 , fieldIdx );
fieldName = mxGetFieldNameByNumber(currentField, fieldIdx );
我已通读这两个函数的文档。如果(在此示例中)currentField 不是 mxArray,则可以返回 NULL,我知道情况并非如此,因为 mxGetFieldNameByNumber() 返回了一些合理的东西。堆空间不足可能是问题,但我已经检查过了,它在 400kb 上。当没有为指定字段分配值时,也可以返回 NULL,但我查看过它的值似乎为零。
有什么想法吗?
【问题讨论】:
如果返回NULL,则表示该字段没有赋值。说“我看过,看起来价值为零”非常有帮助,因为与人们使用了 20 多年的功能损坏相比,您犯错的可能性要大得多。你为什么不创建一个minimal reproducible example 以便我们可以复制这个问题? 如果我无法获得指向 mex 元素的指针,我该如何更改它的值?我想我必须在 MATLAB 中手动执行此操作。 使用mxSetField
和类似方法将矩阵分配到结构字段中。
你需要一个指针才能使用 mxSetField
你需要一个指向你已经拥有的结构的指针,你需要一个指向一个新矩阵的指针,你用mxCreateDoubleMatrx
、mxCreateDoubleScalar
、mxCreateNumericArray
、mxCreateCellMatrix
构造它,mxCreateStructArray
,等等等等等等。
【参考方案1】:
在 MATLAB 级别或通过 mxCreateStruct 在 mex 例程中创建结构时,并非所有字段元素都必须填充。在这种情况下,MATLAB 在这些数据点中物理存储一个 NULL 指针(即 0)(结构本质上是一个 mxArray 指针数组)。例如,假设 X 尚不存在,采用以下代码 sn-p:
X.a = 5;
X(2).b = 7;
X struct 变量实际上有四个元素,分别是 X(1).a、X(1).b、X(2).a 和 X(2).b。但是您只设置了其中两个元素。 MATLAB 如何处理其他元素?答:它只是为这些点存储 NULL 指针。如果您随后在 MATLAB 代码中访问这些 NULL 点,MATLAB 将简单地动态创建一个空的双精度矩阵。
在墨西哥层面,也会发生类似的事情。当您第一次使用 mxCreateStruct 创建结构时,MATLAB 只是用 NULL 值填充所有元素点。然后,您可以根据需要在代码中填充它们,但请注意,将它们保留为 NULL 对于返回 MATLAB 是完全可以接受的。例程 mxGetFieldByNumber 实际上获取元素 mxArray 指针,而 mxGetFieldNameByNumber 获取字段本身的 name ... 两个非常不同的东西。如果您从有效的 mxGetFieldByNumber 调用中得到 NULL 结果(即您的索引没有超出范围),这仅仅意味着该元素从未设置为任何值。您应该永远从有效的 mxGetFieldNameByNumber 调用中获得 NULL 结果,因为所有字段名称都必须存在。
如果您要将上面创建的 X 传递给 mex 例程,然后检查 prhs[0],您会发现以下内容:
mxGetFieldByNumber(prhs[0],0,0)
returns a pointer to an mxArray that is the scalar double 5
mxGetFieldByNumber(prhs[0],0,1)
returns a NULL pointer
mxGetFieldByNumber(prhs[0],1,0)
returns a NULL pointer
mxGetFieldByNumber(prhs[0],1,1)
returns a pointer to an mxArray that is the scalar double 7
mxGetFieldNameByNumber(prhs[0],0)
returns a pointer to the string "a"
mxGetFieldNameByNumber(prhs[0],1)
returns a pointer to the string "b"
【讨论】:
以上是关于MATLAB 的 mxGetFieldByNumber 和 mxGetFieldNameByNumber 返回不一致的结果的主要内容,如果未能解决你的问题,请参考以下文章