gpt4 book ai didi

fortran - 在 Windows 上从 Julia (0.6.2) 调用 Fortran 函数的错误结果

转载 作者:行者123 更新时间:2023-12-02 02:57:26 32 4
gpt4 key购买 nike

我从一个更大的遗留代码库中找到了一个小的辅助子程序,它计算一个向量的一些统计数据并单独编译它,我试图从 Julia (0.6.2) 中调用它进行练习。

首先,我找到了一些论坛帖子和讨论主题,但我想仔细检查一下,因为该语言发展很快,有些可能使用过时的语法 like this one .此外,我使用的是 Windows,我遇到的许多论坛帖子都引用了 .so 文件,据我所知,这些文件适用于 UNIX 系统,而不是 Windows?

我引用的 Fortran 代码(称为 meansd.f)的完整内容是:

SUBROUTINE MEANSD (A,N,ABAR,VAR,STD)
IMPLICIT NONE
C COMPUTE THE MEAN AND STANDARD DEVIATION OF A REAL VECTOR.
C PARAMETERS:
C A: REAL VECTOR TO COMPUTE MEAN AND STANDARD DEVIATION OVER.
C N: LENGTH OF A.
C ABAR: COMPUTED MEAN OF A.
C VAR: VARIANCE OF A.
C STD: COMPUTED STANDARD DEVIATION OF A.
C
REAL A(N)
INTEGER I,N
DOUBLE PRECISION APX, ABAR, VAR, STD, SUM, SUMSQ, DN, Z
C
DN=N
APX=0D0
DO 30 I=1,N
APX=APX+A(I)
30 CONTINUE
APX=APX/DN
SUM=0D0
SUMSQ=0D0
DO 40 I=1,N
Z=A(I)-APX
SUM=SUM+Z
SUMSQ=SUMSQ+Z*Z
40 CONTINUE
ABAR=SUM/DN
VAR=(SUMSQ-(SUM*ABAR))/(DN-1)
STD=DSQRT(VAR)
ABAR=ABAR+APX
RETURN
END

我是用gcc编译的

gcc (x86_64-posix-seh-rev1, Built by MinGW-W64 project) 7.2.0

主要关注 this question ,完成时没有错误:

gfortran -c meansd.f
gfortran -shared -fPIC meansd.o -o meansd.dll

当我使用 Libdl 进行测试时,一切似乎都正常返回,并且返回了一个指针

path=joinpath(pwd(),"meansd.dll")
dl=Libdl.dlopen(path)

然后我尝试构建我的 ccall 函数:

a_ref=Ref{Array{Float64,1}}([5.0,5.0,5.0,5.0,5.0])
i_ref=Ref{Int64}(1)
n_ref=Ref{Int64}(length([5.0,5.0,5.0,5.0,5.0]))
apx_ref=Ref{Float64}(0)
abar_ref=Ref{Float64}(0)
var_ref=Ref{Float64}(0)
std_ref=Ref{Float64}(0)
sum_ref=Ref{Float64}(0)
sumsq_ref=Ref{Float64}(0)
dn_ref=Ref{Float64}(0)
z_ref=Ref{Float64}(0)

ccall((:meansd_,"meansd.dll"),Void,(
Ref{Array{Float64,1}},#A
Ref{Int64}, #I
Ref{Int64}, #N
Ref{Float64}, #APX #I think I have to pass these too?
Ref{Float64}, #ABAR
Ref{Float64}, #VAR
Ref{Float64}, #STD
Ref{Float64}, #SUM
Ref{Float64}, #SUMSQ
Ref{Float64}, #DN
Ref{Float64}, #Z
),a_ref,i_ref,n_ref,apx_ref,
abar_ref,var_ref,std_ref,sum_ref,sumsq_ref,dn_ref,z_ref)

据我所知,这已完成,但 abar_ref 返回为 NaN。然后我也制作了一个 Float/Int 32 版本,完成后 abar_ref 返回为 0.0。我认为我应该使用 64 位,因为我使用 64 位 gfortran 编译。

我想我搞砸了如何传递数组,但我尝试了很多我能想到的不同方法但没有成功。

我也对何时使用 Julia 类型与 ccall 类型(Float32Cint?)感到困惑。我在网上看到过这两种情况的例子,但如果我没看错的话,此时在幕后内置了底层的转换语句来处理这个问题?

最佳答案

编辑:扩展笔记

根据 Pierre 的评论,我返回并重新阅读了文档并设法获得了一个工作版本:

我首先删除了实例化函数调用中命名的变量以外的任何变量:

SUBROUTINE MEANSD (A,N,ABAR,VAR,STD)

接下来,我重新阅读了the documentation section on calling FORTRAN ,特别是这个警告部分。

Warning

For string arguments (char*) the Julia type should be Cstring (if NUL- terminated data is expected) or either Ptr{Cchar} or Ptr{UInt8} otherwise (these two pointer types have the same effect), as described above, not String. Similarly, for array arguments (T[] or T*), the Julia type should again be Ptr{T}, not Vector{T}.

结果代码是:

#declare variables

a=Float32[1.0,2.0,3.0,4.0,5.0] #changed values from OP to have non-zero var/sd for demo
n=length(a) #works as Int32(length(a)) as well?
abar_ref=Ref{Float64}(0)
var_ref=Ref{Float64}(0)
std_ref=Ref{Float64}(0)

#call function

ccall((:meansd_,"meansd.dll"),Void,(
Ptr{Float32},#A
Ref{Int32}, #N
Ref{Float64}, #ABAR
Ref{Float64}, #VAR
Ref{Float64}, #STD
),a,n,abar_ref,var_ref,std_ref)

#check results
abar_ref[] #returns 3.00

var_ref[] #returns 2.50

std_ref[] #returns 1.58

关于fortran - 在 Windows 上从 Julia (0.6.2) 调用 Fortran 函数的错误结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48513650/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com