从朱莉娅传递二维阵列到Fortran

时间:2017-07-04 09:51:43

标签: c fortran julia

我在将Julia的二维阵列传递给Fortran时遇到了麻烦。

将该2d数组传递给C函数可以正常工作。

这是C代码:

#include <stdio.h>
double meanFilter(int **arr, int row, int col)
{
    int i, j, sum=0;
    float mean;
    for (i=0; i<row; i=i+1)
        for (j=0; j<col; j=j+1) {
             sum = sum + arr[i][j];
             printf("%d %d %d %d\n", i, j, arr[i][j], sum);
         }
    mean = (double)sum / (row * col);
    printf("mean=%f\n", mean);
    return mean;
}

我用

编译
icc -o myclib.so myclib.c -fPIC -shared

和我调用C函数的Julia代码:

x = zeros(Cint,5,5)
for i=1:5
    for j=1:5
        x[i,j] = i * j
        print(x[i,j], " ")
    end
    println()
end

refAr = [Ref(x,i) for i=1:size(x,1):length(x)]

aMean = ccall((:meanFilter, :myclib), Float64, (Ptr{Ptr{Cint}}, Cint, Cint), refAr, 5, 5)
println("mean_c=",aMean)

我得到了这个输出:

1 2 3 4 5 
2 4 6 8 10 
3 6 9 12 15 
4 8 12 16 20 
5 10 15 20 25 
0 0 1 1
0 1 2 3
0 2 3 6
0 3 4 10
0 4 5 15
1 0 2 17
1 1 4 21
1 2 6 27
1 3 8 35
1 4 10 45
2 0 3 48
2 1 6 54
2 2 9 63
2 3 12 75
2 4 15 90
3 0 4 94
3 1 8 102
3 2 12 114
3 3 16 130
3 4 20 150
4 0 5 155
4 1 10 165
4 2 15 180
4 3 20 200
4 4 25 225
mean=9.000000
mean_c=9.0

这是Fortran版本:

real(kind=8) function meanFilter(arr, row, col)
    integer, intent(in) :: row, col
    integer, dimension(row,col), intent(in) :: arr
    integer :: i, j, sum

    sum = 0

    do j=1, col
        do i = 1, row
            sum = sum + arr(i,j)
            write(*,*) i, j, arr(i,j), sum
        enddo
    enddo
    meanFilter = real(sum,8)/(row*col)
    write(*,*) "mean=", meanFilter
end function meanFilter

我按照这样编译:

ifort -o myflib.so myflib.f90 -assume byterecl -shared -fPIC

和朱莉娅代码

x = zeros(Cint,5,5)
for i=1:5
    for j=1:5
        x[i,j] = i * j
        print(x[i,j], " ")
    end
    println()
end

refAr = [Ref(x,i) for i=1:size(x,1):length(x)]

aMean = ccall((:simplemodule_mp_meanfilter_, :myflib), Float64, (Ptr{Ptr{Cint}}, Cint, Cint), refAr, 5, 5)
println("mean_f=",aMean)

我得到了这个输出:

signal (11): Segmentation fault
while loading ./fortran_call_in_julia.jl, in expression starting on line 56
simplemodule_mp_meanfilter_ at ./myflib.so (unknown line)
anonymous at ./<missing> (unknown line)
unknown function (ip: 0x2ab08d75fcfa)
unknown function (ip: 0x2ab08d73b606)
jl_load at /usr/bin/../lib64/libjulia.so.0.6 (unknown line)
unknown function (ip: 0x2ab0991bd4e5)
unknown function (ip: 0x2ab0991bd6bb)
jl_apply_generic at /usr/bin/../lib64/libjulia.so.0.6 (unknown line)
unknown function (ip: 0x2ab0990625bf)
unknown function (ip: 0x2ab09906262b)
jl_apply_generic at /usr/bin/../lib64/libjulia.so.0.6 (unknown line)
unknown function (ip: 0x2ab0991c6315)
unknown function (ip: 0x2ab0991c87f4)
unknown function (ip: 0x2ab0991c9288)
jl_apply_generic at /usr/bin/../lib64/libjulia.so.0.6 (unknown line)
unknown function (ip: 0x401d90)
unknown function (ip: 0x401592)
__libc_start_main at /usr/bin/../lib64/libc.so.6 (unknown line)
unknown function (ip: 0x401649)
Allocations: 1664692 (Pool: 1663483; Big: 1209); GC: 1
Segmentation fault (core dumped)

那么,对于fortran版本,我做错了什么?

1 个答案:

答案 0 :(得分:3)

即使对于简单的积分参数,Fortran仍然使用引用调用。另外,您在这里创建了冗余的间接层(在C和Fortran版本中)。所以纠正你的fortran代码的julia包装应该是:

x = zeros(Cint,5,5)
for i=1:5
    for j=1:5
        x[i,j] = i * j
        print(x[i,j], " ")
    end
    println()
end

aMean = ccall((:meanfilter_, "./tst.so"), Float64, (Ref{Cint}, Ref{Cint}, Ref{Cint}), x, 5, 5)
println("mean_f=",aMean) 

我使用gfortran对此进行了测试,因此您的名称可能会有所不同。