我有一个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不兼容?
答案 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
}