2015-02-06 69 views
6

我想從Julia的Fortran庫中調用函數。在這種情況下,我有一個函數eye,它接受一個整數,並返回一個整數的二維數組。從Julia調用Fortran函數,返回一個數組:未知函數,segfault?

的Fortran語言模塊被編譯成使用

$ gfortran -shared -fPIC -o matrix_routines.so matrix_routines.f90 

,然後我試圖從交互朱莉婭解釋這樣的(名字來自nm獲得)稱之爲共享庫:

julia> n=5 
5 

julia> ccall((:__matrix_routines_MOD_eye, "/path/to/library/matrix_routines.so"), Array{Int64,2} , (Ptr{Int64},), &n) 

然而,這立即導致Julia在我身上拋出段錯誤:

signal (11): Segmentation fault 
__matrix_routines_MOD_eye at /path/to/library/matrix_routines.so (unknown line) 
anonymous at no file:0 
unknown function (ip: -1137818532) 
jl_f_top_eval at /usr/bin/../lib/julia/libjulia.so (unknown line) 
eval_user_input at REPL.jl:53 
jlcall_eval_user_input_19998 at (unknown line) 
jl_apply_generic at /usr/bin/../lib/julia/libjulia.so (unknown line) 
anonymous at task.jl:95 
jl_handle_stack_switch at /usr/bin/../lib/julia/libjulia.so (unknown line) 
julia_trampoline at /usr/bin/../lib/julia/libjulia.so (unknown line) 
unknown function (ip: 4199613) 
__libc_start_main at /usr/bin/../lib/libc.so.6 (unknown line) 
unknown function (ip: 4199667) 
unknown function (ip: 0) 
zsh: segmentation fault (core dumped) julia 

我是以錯誤的方式調用函數嗎?什麼是函數的正確名稱? (它看起來不只是eye,因爲這也行不通。)

作爲一個額外的問題:朱莉婭做的任何事情與記憶方向的結果數組? Fortran和Julia都是列專業的,但我想知道是否由於ccall()Julia可能認爲它應該轉移它們?

module matrix_routines 
    implicit none 

    private 

    public :: eye 

    contains 

     pure function eye(n,offset) result(um) !{{{ 
      integer, intent(in) :: n 
      integer, intent(in), optional :: offset 

      integer, dimension(n,n) :: um 

      integer :: i, l, u, os 

      um = 0 

      l = 1 
      u = n 
      os = 0 

      if (present(offset)) then 
       os = offset 
      end if 

      if (abs(os) < n) then 
       if (os > 0) then 
        u = n - os 
       else if (os < 0) then 
        l = 1 - os 
       end if 

       do i=l, u 
        um(i, i+os) = 1 
       end do 
      end if 

     end function eye !}}} 
end module matrix_routines 
+2

可選參數在Fortran中需要顯式接口在玩火之前,您應該知道自己在做什麼。最好的做法是使用帶有C的Fortran 2003 interop(可能還有iso_c_binding模塊)。只有Fortran 2008(或15?)允許C可互操作過程的可選參數。 – 2015-02-07 00:31:23

+0

'gfortran -Wall -fcheck = all ...'有用的輸出嗎? – rickhg12hs 2015-02-07 04:41:25

+1

@VladimirF:謝謝你指出。到目前爲止,我正在使用Fortran程序中的模塊,這當然通過'.mod'文件具有明確的接口。請注意,我已經刪除了'optional'參數,但這仍然導致段錯誤。你是否建議我必須使用'iso_c_binding'? @ rickhg12hs:不,一點都沒有。沒有警告。 – mSSM 2015-02-07 13:52:34

回答

1

有一些問題與您的方法。將數組直接返回給julia是有問題的,因爲除非滿足特定的條件,否則Fortran數組不能與C進行互操作。當你的陣列可互操作(添加bind(C)到你的過程,並給出數組一個C型)編譯器(gfortran)會抱怨:

Error: Return type of BIND(C) function 'um' at (1) cannot be an array 

爲了解決這個問題,我們可以通過虛擬的參數返回數組。您需要將此參數設置爲intent(inout)參數,並在julia中構建數組以避免在Fortran中創建數組時遇到任何內存/範圍問題。

其次,可選參數是有問題的,並跳過Julia文檔,我不確定它甚至被支持。請注意,即使Fortran沒有明確的接口,也可以使用可選參數來調用Fortran,因爲Julia不會與.mod文件進行交互,並且似乎期望C的處理方式,但它可能不起作用(以及Fortran 2008 15.3.7 p2.6似乎表示不支持)。儘管有解決方法 - 您可以使用不同數量的參數創建多個Fortran過程,然後使用它們的可選參數調用過程。

首先,考慮這個Fortran的模塊,從而拉開了與你的榜樣,但削減到只有什麼是必要證明的互操作:

module matrix_routines 
    implicit none 

    private 
    public :: eye 

contains 

    pure subroutine eye(n,um) bind(C,name="eye") !{{{ 
    use, intrinsic :: iso_c_binding, only: c_int 
    implicit none 
    integer(c_int), intent(in) :: n 
    integer(c_int), intent(inout), dimension(n,n) :: um 

    integer :: i, j 

    do j=1,n 
     do i=1,n 
      um(i,j) = i+j 
     end do 
    end do 

    end subroutine eye !}}} 
end module matrix_routines 

請注意,我已經搬到um到作爲一個inout啞參並且因爲我們沒有返回一個值,所以程序改變爲一個子程序。我也刪除了可選參數。我還使用了C interop類型併爲該過程綁定了一個C名稱。你可以在你的問題中編譯這個。

在朱莉婭你現在可以做到以下幾點:

julia> n = 2 
2 

julia> um = zeros(Int32, n, n) 
2x2 Array{Int32,2}: 
0 0 
0 0 

julia> ccall((:eye, "matrix_routines.so"), Void, (Ptr{Int32}, Ptr{Array{Int32,2}}), &n, um) 

julia> um 
2x2 Array{Int32,2}: 
2 3 
3 4 

julia> n = 4 
4 

julia> um = zeros(Int32, n, n) 
4x4 Array{Int32,2}: 
0 0 0 0 
0 0 0 0 
0 0 0 0 
0 0 0 0 

julia> ccall((:eye, "matrix_routines.so"), Void, (Ptr{Int32}, Ptr{Array{Int32,2}}), &n, um) 

julia> um 
4x4 Array{Int32,2}: 
2 3 4 5 
3 4 5 6 
4 5 6 7 
5 6 7 8 

請注意,我們可以稱之爲剛剛:eye,因爲我們用我們的Fortran的bind(C,name="eye")Ç互操作的功能。

最後,如果我們改變DO循環在我的Fortran例子是um(i,j) = i*10+j,我們可以看到,沒有換位發生在數組中:

julia> um 
3x3 Array{Int32,2}: 
11 12 13 
21 22 23 
31 32 33 

您段錯誤能有特別的理由一些事情 - 數據類型不匹配,返回類型問題,可選參數問題或實際調用和變量傳遞不匹配。

+0

我需要爲Julia使用「./matrix_routines.so」來查找庫,然後我得到以「ERROR:MethodError:'convert'沒有方法匹配轉換」開頭的錯誤消息。 – 2016-10-03 22:01:24