如何在Fortran中调用C函数并正确传递uint32_t参数 [英] How to call a C function in Fortran and properly pass uint32_t arguments

查看:269
本文介绍了如何在Fortran中调用C函数并正确传递uint32_t参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



有些测试表明,这也适用于 int32_t ,尽管为了防止最终的陷阱,我想保留 uint32_t



C函数我打电话有以下原型:

pre $ u $ c $ uint32_t encode_(uint32_t x,uint32_t y)
uint32_t decode_(uint32_t dec)

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

  integer :: cod,编码
cod =编码(i,j)

这会产生乱码。因此,我正在使用一种解决方法:

  void code2d_(uint32_t j []){


uint32_t i;

i = encode_(j [0],j [1]);
//下划线是由于FORTRAN命名规则

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

}

然后在Fortran中

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

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

解决方案

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



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

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

  uint32_t编码(uint32_t x,uint32_t y)
uint32_t decode(uint32_t dec)

模块c_procs
接口
函数encode(x,y)bind(C,name =编码)
使用iso_c_binding
整数(c_int32_t)::编码
整数(c_int32_t),value :: x,y
结束函数
函数decode(x, y)bind(C,name =decode)
使用iso_c_binding
整数(c_int32_t):: decode
整数(c_int32_t),value :: dec
结束函数
结束接口
结束模块

...

使用iso_c_binding
使用c_procs

整数(c_int32_t): :cod,i,j
cod =编码(i,j)






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

  rng.f90:173:0:警告:'sub'的类型不是m atch原始声明[-Wlto-type-mismatch] 
ival = sub(jz,jsr)
^
rng_c.c:2:10:note:返回值类型不匹配
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'先前已在此处声明
uint32_t sub(uint32_t a,uint32_t b){



如果您知道自己在做什么,您可以忽略该警告或将其禁用。


Hi I am using a Fortran 90 code to call a C function. Since I am manipulating addresses, the arguments of the C function should be properly matched in Fortran. I am using ifort and icc to compile the code and working on 64 bit machine.

Some testing showed that this will work also with int32_t, although to prevent eventual pitfalls, I would like to keep the uint32_t

The C functions I am calling has the following prototypes

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

I can't call these functions simply by doing something like

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

This will produce gibberish. Therefore I am using a workaround:

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);

}

And subsequently in Fortran

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

Well obviously I have some problem with the mismatch of the argument types. Unfortunately I don't know how to fix this. Since in my decode/encode functions binary address arithmetic is done it is quite important to preserve the uint32_t.

解决方案

You appear to know about iso_c_binding, as you use the tag. Study the Fortran 2003 interoperability with C. Read the tag description and some documentation like http://gcc.gnu.org/onlinedocs/gcc-4.9.0/gfortran/Interoperability-with-C.html . There is no place in modern Fortran for your trailing underscores and similar stuff.

Fortran doesn't have any unsigned types, you have to use the signed. As long as the signed values are positive, it works. If you need larger values, use larger integer type. You can transfer() the lower bytes to int32 if you need it.

Third, Fortran uses some variants of pass by reference by default, especially for bind(c) procedures (it may be a reference to a copy or some other variant). You must use the value attribute to pass by 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)


Recent versions of GCC are able to detect that we are mixing signed and unsigned types during link-time optimizations:

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) {

You can ignore the warning or disable it if you know what you are doing.

这篇关于如何在Fortran中调用C函数并正确传递uint32_t参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆