Chcę wywoływać funkcje z mojej biblioteki Fortran od Julii. W tym przypadku mam funkcję eye
, która pobiera liczbę całkowitą i zwraca dwuwymiarową tablicę liczb całkowitych.Wywołanie funkcji Fortran z Julii, zwrócenie tablicy: nieznana funkcja, segfault?
Moduł Fortran jest kompilowany do wspólnej biblioteki przy użyciu
$ gfortran -shared -fPIC -o matrix_routines.so matrix_routines.f90
a potem ja próbuje wywołać ją z interaktywnym Julia tłumacza takiego (nazwa uzyskanych od nm
):
julia> n=5
5
julia> ccall((:__matrix_routines_MOD_eye, "/path/to/library/matrix_routines.so"), Array{Int64,2} , (Ptr{Int64},), &n)
To jednak natychmiast powoduje, że Julia rzuca na mnie uraz:
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
Czy wywołanie funkcji jest nieprawidłowe? Jaka jest prawidłowa nazwa funkcji? (Wydaje się, że to nie jest tylko eye
, ponieważ to też nie działa.)
Jako dodatkowe pytanie: czy Julia robi coś z orientacją pamięci wynikowych tablic? Fortran i Julia są głównymi kolumnami, ale zastanawiam się, czy ze względu na ccall() Julia może pomyśleć, że powinna je przenieść?
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
Opcjonalne argumenty wymagają jawnego interfejsu w Fortran. Powinieneś wiedzieć, co robisz przed zabawą z ogniem. Najlepiej byłoby użyć interopera Fortran 2003 z C (i prawdopodobnie modułem iso_c_binding). Tylko Fortran 2008 (lub 15?) Pozwala opcjonalnie argumentować na interoperacyjne procedury C. –
Dowolne użyteczne wyjście z 'gfortran -Wall -fcheck = all ...'? – rickhg12hs
@VladimirF: Dziękuję za wskazanie tego. Do tej pory "używałem modułu w moim programie Fortran", który oczywiście ma jawny interfejs poprzez plik '.mod'. Zauważ, że usunąłem argument "opcjonalny", ale nadal powoduje to błąd segfault. Sugerujesz, że muszę użyć 'iso_c_binding'? @ rickhg12hs: Nie, nic w ogóle. Brak ostrzeżeń. – mSSM