编译用于Matlab的C MEX文件时,size_t和mwSize之间的区别是什么?

10

我目前正在将一些32位Matlab的C MEX文件移植到64位Matlab。

在这样做时,我遇到了两种类型,一种来自Matlab人员,另一种是C标准。

这是Matlab文档对 mwSize 的说明:

mwSize (C和Fortran)

尺寸值类型

描述

mwSize 是表示尺寸值(例如数组维度)的类型。使用此函数实现跨平台灵活性。默认情况下,在C中,mwSize 相当于 int。当使用 mex -largeArrayDims 开关时,在C中,mwSize 相当于 size_t。在Fortran中,mwSize 类似地相当于基于平台和编译标志的 INTEGER * 4INTEGER * 8

这是Wikipedia对 size_t 的说明:

size_t 是由多个 C/C++ 标准(例如 C99 ISO/IEC 9899 标准)定义的无符号数据类型,在 stddef.h 中定义。[1] 它可以通过包含 stdlib.h 来进一步导入此文件,因为该文件内部子包括了 stddef.h。[2]

此类型用于表示对象的大小。接受或返回大小的库函数期望它们是此类型或具有 size_t 的返回类型。此外,最常使用的编译器操作符 sizeof 应计算出与 size_t 兼容的值。

size_t 的实际类型取决于平台,一个常见的错误是假设 size_tunsigned int 相同,这可能会导致编程错误,[3][4]例如从32位转移到64位架构时。

就我所看到的,这些类型实际上是相同的。我的问题是:

  1. 它们是相同的吗?
  2. 如果它们是相同的,哪个会被认为是更好的编程风格?理想情况下,我们希望我们的代码也兼容未来的Matlab版本。我猜答案是 mwSize,但我不确定。

编辑:我应该补充说,Matlab人员都在使用这两种类型。例如:

size_t mxGetN(const mxArray *pm);

mxGetN是一个函数,用于获取mxArray的列数。然而,当创建矩阵时,我们使用的是:

mxArray *mxCreateDoubleMatrix(mwSize m, mwSize n, mxComplexity ComplexFlag);

显然输入应该是mwSize。


1
嗯...作为一种基本检查,只需确保它们具有相同的大小:assert(sizeof(size_t) == sizeof(mwSize));并使用其中任何一个。如果assert失败,你就完蛋了。 - pmg
3
如果在编译MEX函数时没有使用-largeArrayDims开关,而size_tint更大的平台上将会导致断言失败。这就是使用mwSize类型定义的整个目的所在。 - Praetorian
+1并感谢@Praetorian。正如我在评论中所说,assert仅用作基本检查:我不了解mex的特定内容。 - pmg
1个回答

12

mwSize 是为了向后兼容和便携性而定义的。正如文档所述,当编译时未使用-largeArrayDims开关时,它映射到一个int,而当使用时,则是size_t。因此,在第一种情况下,mwSize带有符号,但在第二种情况下,它没有。

在您的代码中使用mwSize使您能够在所有平台上重复使用该代码,无论是否使用该标志。

至于您指出的API不一致性,它们确实存在不一致性,但并不是主要问题。 mxGetN()将永远不会返回负数,因此让它返回size_t是可以的。然而(我猜测)旧版本或某些平台上的mex API版本需要传递一个int类型到mxCreateDoubleMatrix(),所以定义函数为输入为mwSize类型使其具备了可移植性和/或向后兼容性。

简而言之,使用mwSize并使用-largeArrayDims来编译mex函数。


1
关于风格的另一个问题:在文档中,mwIndex和mwSize是相同的,除了一个用于索引,一个用于大小。这是什么原因?只是为了使代码更清晰吗?所以在for(i=0; i<=n; i++)中,i将是mwIndex,n将是mwSize,但对我来说,这种区分似乎是不必要的。 - Har
@Har:我从来没有理解为什么需要mwIndex。在某些情况下,它确实使代码更易于理解,但正如你所指出的,当迭代mxArray的某个维度时,你最终会得到一个mwIndex而不是mwSize,我也不喜欢这样。我倾向于对所有东西都使用mwSize。 - Praetorian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接