在 R 中使用 Fortran 子程序?未定义的符号 [英] Use Fortran subroutine in R? Undefined symbol

查看:18
本文介绍了在 R 中使用 Fortran 子程序?未定义的符号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是 对我之前的问题的跟进.我将我的 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.

您可以将 pidboard 保留在模块中,后者甚至不需要互操作.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆