我试图在R studio中调用用Fortran编写的模块,但是后者意外崩溃。
我尝试了其他Fortran示例(pi的阶乘和MC估计),这些示例运行良好。
我看到的无法使用的代码与这些示例之间的唯一区别是,我为纯函数使用了子例程包装器(调用其他纯函数),而这些示例仅依赖于子例程,而事实上我的函数具有 vector 输入。
这是我遵循的过程(或键入的代码):
R CMD SHLIB mypath/myfile.f90 #this compiles without problem; code supplied below.
dyn.load('ptoh') #This is just the given name of the wrapper subroutine
.Fortran('ptoh', dimen=as.integer(dimen), p=as.matrix(p), m=as.integer(m), h=integer(1) )
我在R中任意设置的位置:
dimen<-3; p<-c(4,6,7); m=3;
您是否知道为什么会崩溃?构建包装器的方法正确吗?与
bind(C, name="ptoh_")
相关联的问题吗?我已经非常感谢您的帮助。
吉尔斯
我正在使用最新版本的R在运行HighSierra的Mac上工作。
“myfile.90”中的代码如下:
module hilbert
implicit none
contains
pure function rotate_right(x, d, dimen)
integer, intent(in) :: x, d, dimen
integer :: rotate_right, tmp, mask
mask = 2 ** dimen - 1
rotate_right = shiftr(x, d)
tmp = shiftl(x, dimen - d)
rotate_right = iand(ior(rotate_right, tmp), mask)
end
pure function rotate_left(x, d, dimen)
integer, intent(in) :: x, d, dimen
integer :: rotate_left, tmp, mask
mask = 2 ** dimen - 1
rotate_left = shiftl(x, d)
tmp = shiftr(x, dimen - d)
rotate_left = iand(ior(rotate_left, tmp), mask)
end
pure function gc(i)
integer, intent(in) :: i
integer :: gc
gc = ieor(i, shiftr(i, 1))
end
pure function entry_point(i)
integer, intent(in) :: i
integer :: entry_point
if(i == 0) then
entry_point = 0
else
entry_point = gc(2 * ((i - 1) / 2))
end if
end
pure function exit_point(i, dimen)
integer, intent(in) :: i, dimen
integer :: exit_point, mask
mask = 2 ** dimen - 1
exit_point = ieor(entry_point(mask - i), 2 ** (dimen - 1))
end
pure function inverse_gc(g, dimen)
integer, intent(in) :: g, dimen
integer :: inverse_gc, j
inverse_gc = g
j = 1
do while(j < dimen)
inverse_gc = ieor(inverse_gc, shiftr(g, j))
j = j + 1
end do
end
pure function intercube_g(i) result(g)
integer, intent(in) :: i
integer :: g
g = trailz(ieor(gc(i), gc(i + 1)))
end
pure function intracube_d(i, dimen) result(d)
integer, intent(in) :: i, dimen
integer :: d
if(i == 0) then
d = 0
else if(modulo(i, 2) == 0) then
d = modulo(intercube_g(i - 1), dimen)
else
d = modulo(intercube_g(i), dimen)
end if
end
pure function transform(e, d, b, dimen) result(t)
integer, intent(in) :: e, d, b, dimen
integer :: t
t = rotate_right(ieor(b, e), d + 1, dimen)
end
pure function inverse_transform(e, d, b, dimen) result(t)
integer, intent(in) :: e, d, b, dimen
integer :: t
t = transform(rotate_right(e, d + 1, dimen), dimen - d - 2, b, dimen)
end
pure function ptoh(dimen, p, m) result(h)
integer, intent(in) :: dimen, p(dimen), m
integer :: h, e, d, i, j, l, w
h = 0
e = 0
d = 2
do i = m - 1, 0, -1
l = 0
do j = 1, dimen
l = l + 2 ** (j - 1) * ibits(p(j), i, 1)
end do
l = transform(e, d, l, dimen)
w = inverse_gc(l, dimen)
e = ieor(e, rotate_left(entry_point(w), d + 1, dimen))
d = modulo(d + intracube_d(w, dimen) + 1, dimen)
h = ior(shiftl(h, dimen), w)
end do
end
subroutine ptoh_R_wrapper(dimen, p, m, h) bind(C, name="ptoh_")
integer :: dimen, p(dimen), m, h, ptoh
external ptoh
h = ptoh(dimen, p, m)
end
end
最佳答案
您在模块中使用名称subroutine
公开了包装器"ptoh_"
,但是在R Studio中使用'ptoh'
对其进行了调用。实际上,'ptoh'
是包装(但也公开)的function
的名称。
因此,一旦函数不希望使用此参数,则错误可能来自传递参数h=integer(1)
。
如果这是原因,要解决此问题,可以在R Studio中将调用更改为:
.Fortran('ptoh_', dimen=as.integer(dimen), p=as.matrix(p), m=as.integer(m), h=integer(1))
编辑:
可能导致该错误的另一件事是您正在覆盖包装子例程中的名称
ptoh
。subroutine ptoh_R_wrapper(dimen, p, m, h) bind(C, name="ptoh_")
integer :: dimen, p(dimen), m, h, ptoh
external ptoh
h = ptoh(dimen, p, m)
end
函数
ptoh
在所有模块内部都已经可以使用,包括包装子程序内部(也应删除external ptoh
语句)。将声明更改为此:
subroutine ptoh_R_wrapper(dimen, p, m, h) bind(C, name="ptoh_")
integer :: dimen, p(dimen), m, h
h = ptoh(dimen, p, m)
end
并检查错误是否仍然存在。
最后一点,当您要使子例程与C互操作时,请考虑在互操作参数中使用内部模块
iso_c_binding
中的kind参数(如果适用,还可以使用value
属性)。我对R的了解不足以确保它是必需的,但这并没有伤害。最终代码如下所示:
subroutine ptoh_R_wrapper(dimen, p, m, h) bind(C, name="ptoh_")
use, intrinsic :: iso_c_binding, only: c_int
integer(c_int) :: dimen, p(dimen), m, h
h = ptoh(dimen, p, m)
end
关于r - 调用Fortran模块时R Studio崩溃,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51100869/