Use Fortran subroutine in R? Undefined symbol
Your problem comes down to the declaration of dboard
:
double precision :: pi_est, homepi, pirecv, pisum, dboard
Here you are saying that dboard
is an external function, rather than a module procedure. This explains why there is a symbol dboard_
coming into play. You want to remove that:
double precision :: pi_est, homepi, pirecv, pisum
and instead rely, in pi
on the module procedure-ness of dboard
: pi
already knows about it without this declaration.
Now, beyond that, because pi
is in a module there is going to be some name mangling going on for that subroutine itself. I'd solve this problem by making pi
itself a (C) interoperable procedure.
Module Fpi
IMPLICIT NONE
contains
subroutine pi(avepi, DARTS, ROUNDS) bind(C)
use, intrinsic :: iso_c_binding, only : c_double, c_int
real(c_double), intent(out) :: avepi
integer(c_int), intent(in) :: DARTS, ROUNDS
...
and then using .C
rather than .Fortran
.
You can keep pi
and dboard
in the module, and this latter needn't even be interoperable.
R calling Fortran subroutine with character argument
When you use .C
to call a Fortran subroutine the calling treats character arguments as being C-style char **
. This is not compatible with the Fortran dummy argument of type character(len=255)
.
You have two 'simple' approaches available:
- modify the Fortran subroutine to accept arguments looking like
char **
- use
.Fortran
instead of.C
Modifying the Fortran subroutine to use C interoperability with char **
is better the subject of a new question (for its breadth and being not specific to your R problem). In general, I prefer writing Fortran procedures to be used in R as exposing a C interoperable interface and .C
or .Call
. With what follows you may also come to that conclusion.
Even the R documentation is not optimistic about passing character arguments with .Fortran
:
‘.Fortran’ passes the first (only) character string of a character vector as a C character array to Fortran: that may be usable as ‘character*255’ if its true length is passed separately. Only up to 255 characters of the string are passed back. (How well this works, and even if it works at all, depends on the C and Fortran compilers and the platform.)
You will need to read your documentation about argument passing conventions, such as that for gfortran (consult the appropriate version as these conventions may change).
With .Fortran
and gfortran then with a procedure that is not C-interoperable you will need to pass a "hidden" argument to the Fortran procedure specifying the length of the character argument. That is true for explicit length characters (constant length, even length-1, or not) and assumed-length characters.
For gfortran before version 7, this hidden argument is of (R) type integer. Using pow
of the question, or with assumed-length argument, we can try something like
bar <- .Fortran("pow", as.character("c"), as.double(x), as.double(0.0), 255L)
Note, however, that this is not standard and inherently not portable. Indeed, as janneb comments and the documentation linked above state, how you pass this hidden argument from R to a gfortran-compiled procedure depends on the version of gfortran used. Using 255L
at the end probably won't work beyond gfortran 7. Instead you will need to pass the hidden argument as something matching an integer(c_size_t)
(possibly a 64-bit integer). For compilers other than gfortran you may need to do something quite different.
It really is best to use a C-interoperable procedure either with argument interoperable with char **
(using .C
) or char []
(using .Fortran
). As I say, it's worth going for the first option here, as that leaves more flexibility (like longer characters, more portability, and more character arguments).
Use Fortran subroutine in R? Error: Return type mismatch
You do not use implicit none
. That is very bad! Due to implicit typing dboard
is thought to he default real inside pi
.
Declare it as double precision, or if possible with R, use modules. An interface block can also be used to declare dboard
inside pi
.
using a Fortran module in R?
Thanks to @roygvib and @francescalus this is my working module:
Module Fortranpi
IMPLICIT NONE
contains
subroutine dboard(darts, dartsscore)
integer, intent(in) :: darts
double precision, intent(out) :: dartsscore
double precision :: x_coord, y_coord
integer :: score, n
score = 0
do n = 1, darts
call random_number(x_coord)
call random_number(y_coord)
if ((x_coord**2 + y_coord**2) <= 1.0d0) then
score = score + 1
end if
end do
dartsscore = 4.0d0*score/darts
end subroutine dboard
subroutine pi(avepi, DARTS, ROUNDS) bind(C, name="pi_")
use, intrinsic :: iso_c_binding, only : c_double, c_int
real(c_double), intent(out) :: avepi
integer(c_int), intent(in) :: DARTS, ROUNDS
integer :: MASTER, rank, i, n
integer, allocatable :: seed(:)
double precision :: pi_est, homepi, pirecv, pisum
! we set it to zero in the sequential run
rank = 0
! initialize the random number generator
! we make sure the seed is different for each task
call random_seed()
call random_seed(size = n)
allocate(seed(n))
seed = 12 + rank*11
call random_seed(put=seed(1:n))
deallocate(seed)
avepi = 0
do i = 0, ROUNDS-1
call dboard(darts, pi_est)
! calculate the average value of pi over all iterations
avepi = ((avepi*i) + pi_est)/(i + 1)
end do
end subroutine pi
end module Fortranpi
Fortran shared lib .so shows undefined symbol error
You must use -assume 2underscore
in both compilations, using/not using the option cannot be mixed.
Also extra_fluid2.f90
should be compiled with option -fpic. It's generally a bad idea to use different sets of flags for files that are supposed to go into the same executable or shared object.
WARNING the following symbols are missing
See the mentioned details in 1. In summary:
This local declaration overrides the module function within this
subroutine. Thus the subsequent reference is looking for an external
function of that name, which apparently does not exist, and if it did,
then you would not be computing what you think you are computing. Just
remove this declaration to fix your problem.
Related Topics
How to Do Conditional Grouping of Data in R
Get the Column Number in R Given the Column Name
Adjusting Width of Tables Made with Kable() in Rmarkdown Documents
Predicted Values for Logistic Regression from Glm and Stat_Smooth in Ggplot2 Are Different
Figure Out What Version of R a Function Was Introduced In
One-Class Classification with Svm in R
Read CSV with Dates and Numbers
How to Exit a Shiny App and Return a Value
Hide Certain Columns in a Responsive Data Table Using Dt Package
Convert Comma Separated String to Integer in R
Does the Ternary Operator Exist in R
How to Install R Package from Private Repo Using Devtools Install_Github
Showing Different Axis Labels Using Ggplot2 with Facet_Wrap
Shiny - Can Dynamically Generated Buttons Act as Trigger for an Event
Highlight All Connected Paths from Start to End in Sankey Graph Using R
How to Suppress Automatic Table Name and Number in an .Rmd File Using Xtable or Knitr::Kable