Fermat618's Blog

Happy coding

掉 intel fortran 编译器返回派生类型的方式的坑里了

 
 

最 近写 matlab 与 Fortran 的混编程序时,为了使程序写起来更容易,采用了 Fortran 2003 中 iso_c_binding 模块的一些内容。这些内容的采用使得那些接口写起来 更容易 了,本来松了一口气,想换到 intel fortran 编译器下的时候,又来了那个让我 一看到 就头疼的段错误。

然后又得开始调试了。在仔细查看了程序后,没发现有问题。 然后开始写小程序测试 里面用到的语句。吸引以前的教训,现在仔细检查调用 matlab mex API 后的返回值。可 是 type(c_ptr), 这个 iso_c_binding 模块中规定的放 C 指 针值的数据类型, 却没法打印出来看。

通过 locate iso_c_binding 命令。找到了 intel 的 iso_c_binding.f90 这个文件。打开后查看其内容,发 现

type, bind(c) :: c_ptr
integer(xx), private :: ptr
end type 

type(c_ptr) 的内容被声明为了私有的。 把这个文件拿出来,去掉 private 属性,再手动编译,总算是可以看到 type(c_ptr) 的 内容了。 把同一个 mex 程序用 intel fortran 与 gnu fortran 编译器分别编译两份, 再开一个 matlab, 在里面声明一个变量,传进去,查看各个函数的返回,找到了 mxGetPr 函数返回的结果不对。

 

又另写了一个函数,把 mxGetPr 函数的返回值申明为 integer(8), 再看结果,却又是对 的了。

终于定位到了是 integer*8 和 type(c_ptr) 的区别,才想到可能是 intel 对于后一 种可能采取了不是传值而是传值的方式。另写函数一验证,果然如此。

派生类型与内置类型一样,也是标量。同样的标量,在 intel fortran 中的处理,却是 很不相同,这很超出我预期。这种处理方式真是相当的不统一。标量传值,矢量传址,这 才是统一的方式嘛。

又试了给函数加上 bind(c) 属性,这次终于可以传值了。但是加上了这个属性的函数, 其编译出来的文件的符号的处理又跟普通的 fortran 函数不一样了。 matlab 给 Fortran 的那些 api 的符号名本来是按照 fortran 来的,这么一来就得在 bind(c, name=xxx) 里面写明了。使用 nm 得到实际的符号名后,写死在里面,再加上条件编译,总算是使得 gfortran 与 intel fortran 都可以编译那个程序了,代价就是只能用在 64 平台及开启 了 -largeArrayDims 选项的情况下了。