</no-translation>
<no-translation># </no-translation>Fortran和AnyMath集成
这个项目解决了集成遗留Fortran和AnyMath代码的问题.
目前正在考虑两种情况:
*融入技术计算环境
*集成到仿真环境中
假设您需要集成这样的代码:
<no-translation><no-translation>
subroutine vect_add(a,b,res,len)
integer len
integer i
real, intent(inout) :: res(len)
real a(len)
real b(len)
do concurrent (i = 1:len)
res(i) = a(i) + b(i)
end do
return
end subroutine vect_add
<no-translation>
该子程序将两个向量相加。 我们的任务是在我们的计算中使用这个子程序。
<no-translation>## </no-translation>工作准备
在开始工作之前,我们注意到以下几点:
我们将需要修改子例程的代码,以便它可以正确绑定到名称C或C++。:
<no-translation>subroutine vect_add(a,b,res,len) bind ( C, name="vect_add" )
为了正确使用我们的子例程,它必须编译成共享库。
为此,我们将使用gfortran编译器。
<no-translation>
run(`gfortran vect_add.f90 -shared -fPIC -o vect_add.so`)
</no-translation>
让我们通过运行以下命令来确保我们可以使用已编译的过程:
<no-translation>
run(`objdump -x vect_add.so`)
</no-translation>
此命令输出二进制文件中的字符,我们看到vect_add字符存在于我们的库中。:
<no-translation><no-translation></no-translation></no-translation>` 00000000000010f9 g F .text 00000000000000e1 vect_add <no-translation><no-translation>
<no-translation>
</no-translation>
<no-translation>## </no-translation>融入技术计算环境
为了正确集成,我们将使用动态链接器。 这将允许我们根据需要上传和下载我们的共享库。
<no-translation>
using Pkg; Pkg.add("Libdl")
using Libdl
</no-translation>
下载我们的图书馆:
<no-translation>
lib = Libdl.dlopen("./vect_add.so");
foo = Libdl.dlsym(lib, :vect_add);
</no-translation>
让我们创建测试数据并使用ccall函数调用我们的例程。
Ccall与fortran一起工作的一个特殊功能是Fortran例程的所有参数都通过引用传递。
朱莉娅有一个特殊的类型。 <no-translation>Ref
<no-translation>
Vect_in = Vector{Float32}([1.0,2.0,3.0,4.0,5.0])
Vect_out = copy(Vect_in);
ccall(foo,Nothing,(Ref{Float32},Ref{Float32},Ref{Float32},Ref{Int}), Vect_in, Vect_in, Vect_out, 5)
println("Результат работы кода Fortran : $Vect_out")
</no-translation>
在我们完成库的工作后,我们需要下载它。:
<no-translation>
Libdl.dlclose(lib)
</no-translation>
<no-translation>## </no-translation>集成到仿真环境中
要将编译后的库集成到仿真环境中,我们将使用C功能块。
与任何库一样,使用库函数需要头文件。 很容易看出,我们没有。 但是,gfortran允许您自动生成它。 为此,我们将重新编译我们的代码,另外指定密钥 <no-translation>-fc-prototypesvect_add.h
<no-translation>
res = read(`gfortran vect_add.f90 -shared -o libvect_add.so -fPIC -fc-prototypes`,String);
write("vect_add.h",res);
</no-translation>
打开模型 <no-translation>fort_integration
<no-translation>
demoroot = @__DIR__
demo = joinpath("$demoroot","fortran_caller.engee");
mdl = engee.load(demo)
</no-translation>
此外,我们将配置c函数块的头文件和库的路径。:
<no-translation>
engee.set_param!("fortran_caller/Fortran_is_Here","IncludeDirectories"=>demoroot)
engee.set_param!("fortran_caller/Fortran_is_Here","LibraryDirectories"=>demoroot)
</no-translation>
对我们过程的调用包含在输出代码部分的C函数块中。 由于指针应用于其输入,我们必须传输输入信号的地址。
<no-translation>
</no-translation>
此外,您需要将生成的头文件和库添加到构建信息中。:
<no-translation>
</no-translation>
让我们运行模拟并查看结果。:
<no-translation>
engee.run(mdl);
println("Входной вектор: $(simout["fortran_caller/V_in"].value[1])")
println("Результаты работа Fortran: $(simout["fortran_caller/res"].value[1])")
</no-translation>
<no-translation>## </no-translation>结论
Fortran代码集成是通过首先将此代码编译到共享库中并从模拟环境或交互式脚本调用此库来执行的。 这种方法允许您使用以前的开发,而无需用Julia语言重写代码。