如何在Fortran中调用C函数并正确传递uint32_t参数

时间:2014-07-13 19:35:06

标签: c fortran fortran-iso-c-binding uint32

您好我使用Fortran 90代码来调用C函数。由于我在操作地址,因此应该在Fortran中正确匹配C函数的参数。我正在使用ifort和icc来编译代码并在64位机器上工作。

有些测试显示这也适用于int32_t,虽然为了防止最终陷阱,我想保留uint32_t

我正在调用的C函数具有以下原型

uint32_t encode_(uint32_t x, uint32_t y)
uint32_t decode_(uint32_t dec)

我不能简单地通过执行类似

的操作来调用这些函数
integer :: cod,encode
cod = encode(i,j)

这会产生胡言乱语。因此我正在使用解决方法:

void code2d_(uint32_t j[] ){


uint32_t i;

i=encode_(j[0],j[1]);  
// the underscore is due to the FORTRAN naming convention

printf("Coded %10d  \n",i);

}

随后在Fortran

 integer :: cod,code2d
 cod = code2d(i,j)

很明显,我对参数类型不匹配有些问题。不幸的是我不知道如何解决这个问题。由于在我的解码/编码函数中完成二进制地址算法,因此保留uint32_t非常重要。

2 个答案:

答案 0 :(得分:6)

您在使用标记时似乎了解iso_c_binding。研究Fortran 2003与C的互操作性。阅读标签描述和一些文档,如http://gcc.gnu.org/onlinedocs/gcc-4.9.0/gfortran/Interoperability-with-C.html。现代Fortran中没有地方可用于跟踪下划线和类似的东西。

Fortran没有任何未签名类型,您必须使用签名。只要签名值为正,就可以。如果需要更大的值,请使用更大的整数类型。如果需要,可以transfer()低位字节到int32。

第三,Fortran默认使用一些通过引用传递的变体,特别是对于bind(c)过程(它可能是对副本或其他变体的引用)。您必须使用value属性按值传递。

uint32_t encode(uint32_t x, uint32_t y)
uint32_t decode(uint32_t dec)

module c_procs
  interface
    function encode(x, y) bind(C, name="encode")
      use iso_c_binding
      integer(c_int32_t) :: encode
      integer(c_int32_t), value :: x, y
    end function
    function decode(x, y) bind(C, name="decode")
      use iso_c_binding
      integer(c_int32_t) :: decode
      integer(c_int32_t), value :: dec
    end function
  end interface
end module

...

use iso_c_binding
use c_procs

integer(c_int32_t) :: cod, i, j
cod = encode(i,j)

GCC的最新版本能够检测到我们在链接时优化期间混合了有符号和无符号类型:

rng.f90:173:0: warning: type of 'sub' does not match original declaration [-Wlto-type-mismatch]
     ival = sub(jz, jsr)
^
rng_c.c:2:10: note: return value type mismatch
 uint32_t sub(uint32_t a, uint32_t b) {
          ^
/usr/include/stdint.h:51:23: note: type 'uint32_t' should match type 'int'
 typedef unsigned int  uint32_t;
                       ^
rng_c.c:2:10: note: 'sub' was previously declared here
 uint32_t sub(uint32_t a, uint32_t b) {

如果你知道自己在做什么,可以忽略警告或禁用它。

答案 1 :(得分:0)

您可以编写一个C函数,该函数接受C_INT(或C中的int),然后将其转换为uint32_t。然后,您可以从Fortran链接到此页面。

在C中:

uint32_t to_uint32_t ( int i ) {
    return (uint32_t)i; //cast actually not needed since it implicitly converts
}

在fortran中:

module convert
    interface
        integer(C_INT32_T) function integer_to_uint32_t_C ( i ) bind (c,name="to_uint32_t")
            use iso_c_binding
            use user32_constants_types
            integer(c_int), value :: i
        end function
    end interface

end module convert

然后,您可以使用integer_to_uint32_t_C将Fortran整数值传递给需要uint32_t的C函数。另外,您可能想制作一个C函数,将其转换回普通的ole int,以便可以在Fortran中使用结果。