Reputation: 1652
I have a Fortran subroutine that selects a function based on the value of a string and then executes that function.
!! 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
I would like to call this subroutine from an R script.
# file:select.R
dyn.load("select.so")
.Fortran("simple", "add")
.Fortran("simple", "diff")
As a standalone Fortran program
that takes a command line argument, this runs perfectly fine. It's even insensitive to spaces before or after modname
. However, when I try to pass in a character as an argument from R, it correctly re-prints the character (without any extra spaces), but then doesn't recognize it as a case
and skips to the default
. What is going on here? Is there some encoding issue with R characters that makes them incompatible with Fortran?
Upvotes: 3
Views: 779
Reputation: 159
I believe your select case statement is not properly matching because the modname
is 10 characters long, and none of your cases cover a string of that length. The best thing to do is to also pass in the length of the string to your Fortran function, then use this to slice your character array.
subroutine simple(modname,length)
then select case (modname(1:length))
Fortran strings are not zero terminated like the C language. It's an array based language.
Also when passing a string from R to .Fortran
, it might be better to pass it as raw bytes. Simple example below. First is the Fortran code, then the R wrapper code.
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
}
Upvotes: 2