将字符/字符串从R传递给Fortran

时间:2015-05-13 18:32:25

标签: r fortran character

我有一个Fortran子例程,它根据字符串的值选择一个函数,然后执行该函数。

!! file:select.f90
module funcs
    contains
        subroutine add(x, y, xy)
            real :: x, y, xy
            xy = x + y
            return
        end subroutine

        subroutine diff(x, y, xy)
            real :: x, y, xy
            xy = x - y
            return
        end subroutine
end module

subroutine simple(modname)
    use funcs

    procedure(), pointer :: model => null()

    character(10) :: modname
    real :: x, y, xy

    print *, "-",modname,"-"
    select case (modname)
        case("add")
            model => add
        case("diff")
            model => diff
        case default
            print *, "No model with that name!"
            stop
    end select

    x = 4
    y = 3
    call model(x, y, xy)
    print *, xy

end subroutine

我想从R脚本中调用这个子例程。

# file:select.R
dyn.load("select.so")
.Fortran("simple", "add")
.Fortran("simple", "diff")

作为一个带有命令行参数的独立Fortran program,这运行得很好。它甚至对modname之前或之后的空格不敏感。但是,当我尝试从R传入一个字符作为参数时,它会正确地重新打印该字符(没有任何额外的空格),但是然后它不会将其识别为case并跳到{{ 1}}。这里发生了什么? R字符是否存在编码问题,使它们与Fortran不兼容?

1 个答案:

答案 0 :(得分:2)

我相信您的select case语句不正确匹配,因为modname的长度为10个字符,并且您的所有case都不包含该长度的字符串。最好的办法是将字符串的长度也传递给您的Fortran函数,然后使用它来切片您的字符数组。

subroutine simple(modname,length)

然后select case (modname(1:length))

Fortran字符串不像C语言那样以零结尾。这是一种基于数组的语言。

另外,当将字符串从R传递到.Fortran时,最好将其作为原始字节传递。下面的简单示例。首先是Fortran代码,然后是R包装器代码。

subroutine print_this ( str, length )
 integer :: length
 character(length) :: str
 print *, str(1:length)
end subroutine print_this 

test <- function(str) {
  l <- nchar(str) 
  str_raw <- character(l)
  str_raw <- charToRaw(str)
  .Fortran("print_this",str_raw,l)
  l #returns length
}