Alexey Shiklomanov
Alexey Shiklomanov

Reputation: 1652

Passing characters/strings from R to Fortran

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

Answers (1)

Don F
Don F

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

Related Questions