我正在尝试使用Absoft Pro Fortran 13.0.3,64位构建一个Fortran DLL,用于R,Windows 7 64位。
这是我的文件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中找到它,而英特尔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.
但是,如果我重新启动R,则以下操作不起作用(请注意我只删除了is.loaded
测试):
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)。但我没有暗示它可能是什么。
欢迎任何想法!
好的,解决了弗拉基米尔F的一个好问题(见评论)。
实际上,必须将下划线附加到符号名称。由于编译器选项无法执行此操作,因此需要CDEC$
指令(请参阅HP或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 forum的第二个解决方案:实际上我从一开始就错了。与我的想法相反,不需要使用dll_export语句,它甚至引入了问题:没有它,编译器会附加下划线。默认情况下会导出所有符号,如gfortran中所示。所以正确的代码就是:
subroutine mycalcf(a,b,c)
real*8 a,b,c
c=a+b*b
end
甚至不需要任何选项来获取小写符号,它也是默认值。
然而,还有一个问题:R函数.Fortran
是否总是添加下划线(有没有办法告诉它不要?),如果它总是添加,为什么调用预先调用is.loaded
时的工作? R似乎在这里做了一些奇怪的事情。
我尝试跟踪R源代码中的is.loaded
(do_isloaded
中最多src\main\dotcode.c
),但无济于事。