我正在尝试使用 Absoft Pro Fortran 13.0.3(64 位)构建 Fortran DLL,以便在 Windows 7 64 位上的 R 中使用。
这是我的文件 mycalc.f (这是一个愚蠢的示例,只是为了测试功能):
subroutine mycalcf(a,b,c)
real*8 a,b,c
dll_export mycalcf
c=a+b*b
end
该声明dll_export
不是标准的,但在某些 Fortran 编译器中可以找到(AFAIK 在 Lahey 和 CVF 中也可以找到,而 Intel Fortran 有一个编译器指令)。它只是告诉编译器要导出哪些符号。
我编译成功:af90 -m64 -dll -YDLL_NAMES=LCS mycalc.f -o mycalc.dll
选项-YDLL_NAMES=LCS
告诉编译器构建一个带有小写符号的库,这对于 R 来说似乎更好。
如果我跑dumpbin /exports mycalc.dll
,我可以在导出的符号中找到 mycalcf,小写,前后没有任何下划线。
现在,在 R(64 位版本)中,可以执行以下操作:
dyn.load("mycalc.dll")
is.loaded("mycalcf")
.Fortran("mycalcf", a=4, b=5, c=0)
正如预期的那样,返回时我得到 c=29。
BUT,如果我重新启动 R,以下内容将不起作用(注意我只删除了is.loaded
test):
dyn.load("mycalc.dll")
.Fortran("mycalcf", a=4, b=5, c=0)
我收到错误:Fortran symbol name "mycalcf" not in load table
.
现在我的问题是:为什么这个测试如此重要?
作为比较,当我尝试使用 gfortran 而不是 Absoft 进行相同操作时,我完全没有问题。我编译:gfortran -m64 -shared -o mycalc2.dll mycalc.f
(注释掉 dll_export 语句之后,gfortran 不需要该语句,甚至也无法识别该语句)。
然后在R中:
dyn.load("mycalc2.dll")
.Fortran("mycalcf", a=4, b=5, c=0)
我得到 c=29,没有错误。
现在,我怀疑 gcc 链接器所做的某些事情不是由 Absoft 链接器(实际上是 Microsoft 的 link.exe)自动完成的。但我不知道它会是什么。
欢迎任何想法!
好的,Vladimir F 提出了一个很好的问题后的解决方案(请参阅评论)。
实际上,必须在符号名称后添加下划线。由于无法通过编译器选项来完成此操作,因此需要CDEC$
指令(参见HP or Intel文档)。
这里很简单:
subroutine mycalcf(a,b,c)
CDEC$ attributes alias:'mycalcf_' :: mycalcf
real*8 a,b,c
dll_export mycalcf
c=a+b*b
end
第二个解决方案,来自Absoft论坛: 其实我从一开始就错了。与我的想法相反,不需要使用 dll_export 语句,它甚至引入了问题:没有它,编译器会附加下划线。默认情况下会导出所有符号,如 gfortran 中一样。所以正确的代码很简单:
subroutine mycalcf(a,b,c)
real*8 a,b,c
c=a+b*b
end
甚至不需要任何选项来获取小写符号,这也是默认值。
然而,仍然存在一个问题:R 函数是否有效?.Fortran
总是添加下划线(有没有办法告诉它不要这样做?),如果总是添加,为什么调用在is.loaded
是提前调用的吗? R 似乎在这里做了一些奇怪的事情。