Hi,

I've been trying to pass a character vector from R to a FORTRAN subroutine. 
There have been several posts discussing this issue (e.g. 
http://tolstoy.newcastle.edu.au/R/help/98a/0547.html, 
http://tolstoy.newcastle.edu.au/R/help/05/10/13558.html, 
http://tolstoy.newcastle.edu.au/R/help/01a/2577.html, 
http://tolstoy.newcastle.edu.au/R/help/01c/1795.html, 
http://tolstoy.newcastle.edu.au/R/devel/03a/0620.html, 
http://tolstoy.newcastle.edu.au/R/devel/99b/0323.html). According to R-exts 
(section 5.2, Interface functions .C and .Fortran), there are severe 
limitations on this: "Only the first element of the character vector is passed 
in, as a fixed-length (255) character array".

I think there may be a work-around, although I'm no FORTRAN expert, and I would 
like to hear your thoughts about it. The basic idea is to convert the strings 
to integers, transfer the resulting integer vector to FORTRAN, and then convert 
back to characters. Here's an example:

####### start of fortran code
       subroutine readchar(intstring,stringlengths,totalnchar,nstrings)
       implicit none
C     global variables
       integer totalnchar,nstrings
       integer intstring(totalnchar),stringlengths(nstrings)
C     local variables
       integer j,count, stringLength, i1, i2
       parameter(stringLength = 1000)
       character c*(stringLength)
C     functions, etc.
       intrinsic char,min

c     convert from integer to character
       do j = 1,min(stringLength,totalnchar)
          write(c(j:j),'(A)') char(intstring(j))
       end do

       count=0
       do j = 1,nstrings
          i1 = (count+1)
          i2 = min(count+stringlengths(j),stringLength)
c     print the jth string
          write(*,*) c(i1:i2)
c     add a blank line after it
          write(*,*)
          count = count+stringlengths(j)
c     avoid reading past the bounds of the character variable
          if(count .ge. stringLength) then
             goto 10
          end if
       end do

 10    continue

       return
       end
####### end of fortran code

####### start of R code
strings <- c("donald duck",
             "When trying to express oneself, it's frankly quite absurd,
To leaf through lengthy lexicons to find the perfect word.
A little spontaniaty keeps conversation keen,
You need to find a way to say, precisely what you mean...
Supercalifragilisticexpialidocious!
Even though the sound of it is something quite atrosicous!
If you say it loud enough, you'll always sound precocious",
             " 
!\"#$%&'()*+,-./0123456789:;<=>?...@abcdefghijklmnopqrstuvwxyz[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~")

system('R CMD SHLIB readchar.f')

dyn.load('readchar.so')
A <- .Fortran('readchar',
              as.integer(unlist(sapply(strings,charToRaw),use.names=FALSE)),
              as.integer(nchar(strings)),
              as.integer(sum(nchar(strings))),
              as.integer(length(strings)))

dyn.unload('readchar.so')
####### end of R code

Running this gives:

> strings <- c("donald duck",
+              "When trying to express oneself, it's frankly quite absurd,
+ To leaf through lengthy lexicons to find the perfect word.
+ A little spontaniaty keeps conversation keen,
+ You need to find a way to say, precisely what you mean...
+ Supercalifragilisticexpialidocious!
+ Even though the sound of it is something quite atrosicous!
+ If you say it loud enough, you'll always sound precocious",
+              " 
!\"#$%&'()*+,-./0123456789:;<=>?...@abcdefghijklmnopqrstuvwxyz[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~")
>
> system('R CMD SHLIB readchar.f')
g77   -fpic  -g -O2 -c readchar.f -o readchar.o
gcc -std=gnu99 -shared -L/usr/local/lib64 -o readchar.so readchar.o  -lg2c -lm
>
> dyn.load('readchar.so')
> A <- .Fortran('readchar',
+               as.integer(unlist(sapply(strings,charToRaw),use.names=FALSE)),
+               as.integer(nchar(strings)),
+               as.integer(sum(nchar(strings))),
+               as.integer(length(strings)))
 donald duck

 When trying to express oneself, it's frankly quite absurd,
To leaf through lengthy lexicons to find the perfect word.
A little spontaniaty keeps conversation keen,
You need to find a way to say, precisely what you mean...
Supercalifragilisticexpialidocious!
Even though the sound of it is something quite atrosicous!
If you say it loud enough, you'll always sound precocious

  
!"#$%&'()*+,-./0123456789:;<=>?...@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

>
> dyn.unload('readchar.so')
>

One obvious weakness is that you have to specify in advance the maximum number 
of characters that can be passed to the subroutine. Another possible problem is 
that this maximum may be also be rather limited (e.g. one fortran 77 guide says 
that it is system-dependent, and while 255 characters should be safe, many 
systems allow up to 32767 characters: 
http://www.star.le.ac.uk/~cgp/prof77.html#tth_sEc5.1).

Despite these weaknesses, it looks like (at least on some systems) it is 
possible to pass character vectors to FORTRAN subroutines, avoiding the 
restrictions suggested in R-Exts. In the above example, several strings are 
passed to the subroutine, and one of them is longer than the 255 character 
limit (as noted in R-Exts). It also suggests obvious ways character data can be 
passed back into R.

But I admit, it is a bit of a hack...

Jeremy Silver



        [[alternative HTML version deleted]]

______________________________________________
R-help@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.

Reply via email to