在 R 中使用 Fortran 子程序?未定义的符号 [英] Use Fortran subroutine in R? Undefined symbol
问题描述
这是 对我之前的问题的跟进一个>.我将我的 Fortran 代码包装在一个模块中,现在它在我运行时编译:
R CMD SHLIB ./Fortran/Fpi.f90
这是我的 Fortran 代码:
模块 Fpi隐式无包含子程序 pi(avepi, DARTS, ROUNDS)双精度,intent(out) :: avepi整数,intent(in) :: DARTS, ROUNDS整数 :: MASTER, rank, i, n整数,可分配 :: seed(:)双精度 :: pi_est、homepi、pirecv、pisum、dboard!我们在顺序运行中将其设置为零排名 = 0!初始化随机数生成器!我们确保每个任务的种子都不同调用 random_seed()调用 random_seed(size = n)分配(种子(n))种子 = 12 + 排名*11调用 random_seed(put=seed(1:n))释放(种子)平均 = 0我 = 0,ROUNDS-1pi_est = dboard(飞镖)!计算所有迭代中 pi 的平均值avepi = ((avepi*i) + pi_est)/(i + 1)结束做结束子程序 pi双精度函数 dboard(飞镖)整数,意图(in)::飞镖双精度 :: x_coord, y_coord整数 :: 分数,n分数 = 0做 n = 1,飞镖调用随机数(x_coord)调用随机数(y_coord)如果 ((x_coord**2 + y_coord**2) <= 1.0d0) 那么分数 = 分数 + 1万一结束做dboard = 4.0d0*score/darts结束函数端模块 Fpi
我正在尝试在 R 中运行它:
mypi <- function(DARTS, ROUNDS) {dyn.load("./Fortran/Fpi.so")retvals <- .Fortran("pi", DARTS = as.integer(DARTS) , ROUNDS = as.integer(ROUNDS), avepi = as.numeric(1))返回(retvals$avepi)}mypi(DARTS = 50000, ROUNDS = 10)
我得到这个错误:
dyn.load("./Fortran/Fpi.so") 中的错误:无法加载共享对象/home/ignacio/local/projects/PI/./Fortran/Fpi.so":/home/ignacio/local/projects/PI/./Fortran/Fpi.so:未定义符号:dboard_
你的问题归结为dboard
的声明:
双精度 :: pi_est, homepi, pirecv, pisum, dboard
这里你说 dboard
是一个 external 函数,而不是一个模块过程.这就解释了为什么会有一个符号 dboard_
起作用.你想删除它:
双精度 :: pi_est, homepi, pirecv, pisum
而是在 pi
中依赖 dboard
的模块过程性:pi
已经知道它没有这个声明.pip>
现在,除此之外,因为 pi
在一个模块中,所以该子例程本身将会进行一些名称修改.我将通过使 pi
本身成为 (C) 可互操作的过程来解决这个问题.
模块 Fpi隐式无包含子程序 pi(avepi, DARTS, ROUNDS) 绑定(C)使用,内在 :: iso_c_binding,仅:c_double,c_int真实(c_double),意图(出)::avepi整数(c_int),意图(in)::DARTS,ROUNDS...
然后使用 .C
而不是 .Fortran
.
您可以将 pi
和 dboard
保留在模块中,后者甚至不需要互操作.
This is a follow up to my previous question. I wrapped my Fortran code in a module and now it compiles when I run:
R CMD SHLIB ./Fortran/Fpi.f90
This is my Fortran code:
Module Fpi
IMPLICIT NONE
contains
subroutine pi(avepi, DARTS, ROUNDS)
double precision, intent(out) :: avepi
integer, intent(in) :: DARTS, ROUNDS
integer :: MASTER, rank, i, n
integer, allocatable :: seed(:)
double precision :: pi_est, homepi, pirecv, pisum, dboard
! 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
pi_est = dboard(DARTS)
! calculate the average value of pi over all iterations
avepi = ((avepi*i) + pi_est)/(i + 1)
end do
end subroutine pi
double precision function dboard(darts)
integer, intent(in) :: darts
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
dboard = 4.0d0*score/darts
end function
end module Fpi
I'm trying to run this in R:
mypi <- function(DARTS, ROUNDS) {
dyn.load("./Fortran/Fpi.so")
retvals <- .Fortran("pi", DARTS = as.integer(DARTS) , ROUNDS = as.integer(ROUNDS), avepi = as.numeric(1))
return(retvals$avepi)
}
mypi(DARTS = 50000, ROUNDS = 10)
and I get this error:
Error in dyn.load("./Fortran/Fpi.so") :
unable to load shared object '/home/ignacio/local/projects/PI/./Fortran/Fpi.so':
/home/ignacio/local/projects/PI/./Fortran/Fpi.so: undefined symbol: dboard_
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 中使用 Fortran 子程序?未定义的符号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!