2015-02-06 5 views
6

मैं जूलिया से अपने फोरट्रान पुस्तकालय में कार्यों को कॉल करना चाहता हूं। इस मामले में, मेरे पास एक कार्य eye है जो एक पूर्णांक लेता है, और पूर्णांक की दो-आयामी सरणी देता है।जूलिया से फोरट्रान फ़ंक्शन को कॉल करना, एक सरणी लौटना: अज्ञात फ़ंक्शन, segfault?

julia> n=5 
5 

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

:

फोरट्रान मॉड्यूल

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

और का उपयोग कर उसके बाद मैं इसे इंटरैक्टिव जूलिया ऐसा दुभाषिया (नाम nm से प्राप्त) से कॉल करने का प्रयास कर रहा हूँ एक साझा पुस्तकालय में संकलित किया गया है हालांकि, इसके परिणामस्वरूप जूलिया ने मुझे एक सेगफॉल्ट फेंक दिया:

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 प्रतीत नहीं होता है, क्योंकि यह या तो काम नहीं करता है।)

अतिरिक्त प्रश्न के रूप में: क्या जूलिया परिणामी सरणी के स्मृति-अभिविन्यास के साथ कुछ भी करता है? फोरट्रान और जूलिया कॉलम-प्रमुख दोनों हैं, लेकिन मुझे आश्चर्य है कि अगर सीसीएल() के कारण जूलिया सोच सकता है कि उन्हें उन्हें छोटा करना चाहिए?

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

वैकल्पिक तर्कों को फोरट्रान में स्पष्ट इंटरफ़ेस की आवश्यकता होती है आपको पता होना चाहिए कि आग से खेलने से पहले आप क्या कर रहे हैं। सी (और संभवतः iso_c_binding मॉड्यूल) के साथ फोरट्रान 2003 इंटरऑप का उपयोग करना सबसे अच्छा होगा। केवल फोरट्रान 2008 (या 15?) सी इंटरऑपरेबल प्रक्रियाओं के लिए वैकल्पिक तर्क की अनुमति देता है। –

+0

'gfortran -Wall -fcheck = all ...' से कोई उपयोगी आउटपुट? – rickhg12hs

+1

@VladimirF: इसे इंगित करने के लिए धन्यवाद। अब तक, मैं अपने फोरट्रान 'प्रोग्राम' में मॉड्यूल का उपयोग कर रहा था, जिसमें निश्चित रूप से '.mod' फ़ाइल के माध्यम से एक स्पष्ट इंटरफ़ेस है। नोट, मैंने 'वैकल्पिक' तर्क हटा दिया है, लेकिन यह अभी भी एक segfault में परिणाम है। क्या आप सुझाव दे रहे हैं कि मुझे 'iso_c_binding' का उपयोग करना है? @ rickhg12hs: नहीं, कुछ भी नहीं। कोई चेतावनी नहीं – mSSM

उत्तर

1

आपके दृष्टिकोण के साथ कुछ समस्याएं हैं। जूलिया को सीधे एक सरणी लौटाना समस्याग्रस्त है क्योंकि फोरट्रान सरणी सी के साथ अंतःक्रियाशील नहीं होती है जब तक कि विशिष्ट स्थितियों को पूरा नहीं किया जाता है। जब आप सरणी अंतर-संचालित कर (अपनी प्रक्रिया के लिए bind(C) जोड़ सकते हैं और सरणी एक सी प्रकार दे) संकलक (gfortran) शिकायत:

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

इस के आसपास पाने के लिए हम एक डमी तर्क के माध्यम से सरणी लौट सकते हैं। आप इसे intent(inout) तर्क बनाना चाहते हैं और फोरट्रान में सरणी बनाने के साथ किसी भी स्मृति/स्कोप समस्याओं से बचने के लिए जुलिआ में सरणी का निर्माण करना चाहते हैं।

दूसरा, वैकल्पिक तर्क समस्याग्रस्त है और जूलिया दस्तावेज़ों को स्किम करना मुझे यकीन नहीं है कि यह भी समर्थित है। ध्यान दें कि फोरट्रान भी फोरट्रान को एक स्पष्ट इंटरफ़ेस के बिना वैकल्पिक तर्क के साथ कॉल नहीं कर सकता है और जूलिया .mod फ़ाइल से सहभागिता नहीं करता है और ऐसा लगता है कि चीजों को करने का सी तरीका है, यह शायद काम नहीं करेगा (और फोरट्रान 2008 15.3.7 पी 2.6 लगता है कि यह समर्थित नहीं है)। यद्यपि कामकाज हैं - आप तर्कों की विभिन्न संख्याओं के साथ कई फोरट्रान प्रक्रियाएं बना सकते हैं और फिर उनसे वैकल्पिक तर्कों के साथ प्रक्रिया को कॉल कर सकते हैं।

पहले, इस फोरट्रान मॉड्यूल है, जो अपने उदाहरण के साथ शुरू किया, लेकिन सिर्फ तुम क्या इंटरॉप प्रदर्शित करने के लिए आवश्यक है करने के लिए नीचे मुकाबले जाता है पर विचार करें:

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 

ध्यान दें कि मैं एक inout डमी तर्क होने के um स्थानांतरित कर दिया है और चूंकि हम एक मूल्य वापस नहीं कर रहे हैं, प्रक्रिया को एक सबराउटिन में बदल दिया है। मैंने वैकल्पिक तर्क भी हटा दिया है। मैंने सी इंटरऑप प्रकारों का भी उपयोग किया है और प्रक्रिया में सी नाम को बाध्य किया है। आप इसे अपने प्रश्न के रूप में संकलित कर सकते हैं।

जूलिया में आप अब निम्न कर सकते हैं:

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 के बाद से हम अपने फोरट्रान में bind(C,name="eye") सी इंटरॉप इस्तेमाल किया कॉल कर सकते हैं।

और अंत में, अगर हम अपना फोरट्रान उदाहरण में करते पाश बदलने um(i,j) = i*10+j होने के लिए, हम देख सकते हैं कि कोई भी स्थानांतरण सरणी में होता है:

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

अपने segfault हो सकता था के लिए विशेष कारण कई चीजें हैं - बेमिसाल डेटा प्रकार, रिटर्न प्रकार के साथ समस्याएं, वैकल्पिक तर्क के साथ समस्याएं या वास्तविक कॉल और विसंगतियों में विसंगतियां।

+0

मुझे लाइब्रेरी खोजने के लिए जूलिया के लिए "./matrix_routines.so" का उपयोग करने की आवश्यकता है, फिर मुझे त्रुटि त्रुटि मिलती है "त्रुटि: विधि त्रुटि: 'कनवर्ट करें' में कोई विधि मिलान नहीं है"। –

संबंधित मुद्दे