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]]