2014-03-06 2 views
3

fgsl을 수정하므로 함수 이름 대신 함수 포인터를 전달할 수 있습니다. 이를 위해 Fortran의 bind (c) 함수를 사용하고, c_funloc을 호출하고, C 함수를 호출하고, 파생 된 유형 (c_ptr)에 할당합니다. 그러나 C 코드는 코드를 구현하는 방법에 따라 segfault를 제공합니다.Fortran-C 함수 포인터가 특정 상황에서 C 코드의 seg 오류를 일으키는 경우

C 코드 :

#include <stdio.h> 
#include <stdlib.h> 
struct function_struct 
{ 
    double (* function) (double x); 
}; 

typedef struct function_struct gsl_function; 

gsl_function *function_cinit(double (*func)(double x)) { 

    gsl_function *result; 

    if (func) { 
     printf("Passed Function Not Null\n"); 
    } 

    printf("The size of gsl_function is %zu\n", sizeof(gsl_function)); 
    result = (gsl_function *) malloc(sizeof(gsl_function)); 
    result->function = func; 

    printf("Res: %f\n", (*func)(2.0)); 

    if (result) { 
     printf("Result Not Null\n"); 
    } 

    return result; 
} 

지금 내 주요 프로그램/모듈 :

module integral 
    use, intrinsic :: iso_c_binding 
    implicit none 

    !Interface to call C function 
    interface 
    function function_cinit(func) bind(c) 
     import 
     type(c_funptr), value :: func 
     type(c_ptr) :: function_cinit 
    end function function_cinit 
    end interface 

!Proc pointer interface for arbitrary math function f(x) which is passed to the C function so it can be used in a library that requires 
! a pointer to a function 
    abstract interface 
    function rhox(r) bind(c) 
     use, intrinsic :: iso_c_binding 
     real(c_double), value :: r 
     real(c_double) :: rhox 
    end function rhox 
    end interface 

contains 
    ! Arbitary function f(x) = x 
    function f(x) bind(c) 
    use, intrinsic :: iso_c_binding 
    real(c_double) :: f 
    real(c_double), value :: x 
    f = x 
    end function f 

!Function passed by name 
    function func_init(func) 
    interface 
     function func(x) bind(c) 
     use, intrinsic :: iso_c_binding 
     real(c_double), value :: x 
     real(c_double) :: func 
     end function func 
    end interface 

    type(c_ptr) :: func_init 
    type(c_funptr) :: fp 

    fp = c_funloc(func) 
    func_init = function_cinit(fp) 
    end function func_init 

    !Function passed with procedure pointer 
    function fp_init(fun) 
    procedure(rhox), pointer :: fun 
    type(c_ptr) :: fp_init 
    type(c_funptr) :: fp 

    fp = c_funloc(fun) 

    call c_f_procpointer(fp, fun) 

    fp_init = function_cinit(fp) 
    end function fp_init 

    !C_funptr passed directly 
    function cfun_ptr_init(fun) 
    type(c_funptr) :: fun 
    type(c_ptr) cfun_ptr_init 

    cfun_ptr_init = function_cinit(fun) 
    end function cfun_ptr_init 


end module integral 


program bsp 
    use integral 
    use, intrinsic :: iso_c_binding 
    implicit none 

    procedure(rhox), pointer :: fptr 
    type(c_funptr) :: cptr 
    type(c_ptr) :: c_result 

    fptr => f 

    cptr = c_funloc(fptr) 


    call c_f_procpointer(cptr, fptr) 

    !This works, calling the cptr after calling c_f_procpointer on c_funptr obtained by using c_funloc 
    print *, "Evaluate C Function: ", fptr(2.0_c_double) 
    print *, "" 

    !This Works f(2.0) = 2.0, valid pointer 
    c_result = func_init(f) 
    print *,"Passing Function Directly Successful" 
    print *, " " 

    !This works, calling C function directly from main program passing it the c_funloc of the procedure8 
    c_result = function_cinit(cptr) 
    print *,"Calling C Function Directly Successful" 
    print *, " " 

    c_result = cfun_ptr_init(cptr) 
    print *,"Calling C function by Passing c_funptr Successful" 
    print *, " " 

    !Segmentation Fault 11, calling C function indirectly from function which I pass the Fortran Proc pointer 
    c_result = fp_init(fptr) 

end program bsp 
+0

14.0.2를 사용하고 있습니까? – IanH

+0

14.0.1을 사용하여 업데이트 중입니다. @IanH – Exascale

+0

14.0.2에서 BIND (C) 함수에 대한 포인터를 VALUE에 전달하는 것과 관련된 버그 수정이있었습니다. http://software.intel.com/en-us/forums/topic/498635를 참조하십시오. – IanH

답변

0

답을 찾을! 나는 코드가 프로 시저 포인터를 받아들이도록 변경할 필요가 없음을 알았다.

!Function passed with procedure pointer 
    function fp_init(fun) 
    !Changed from: 
    !procedure(rhox), pointer :: fun 
    procedure(rhox):: fun 
    type(c_ptr) :: fp_init 
    type(c_funptr) :: fp 

    fp = c_funloc(fun) 

    call c_f_procpointer(fp, fun) 

    fp_init = function_cinit(fp) 
    end function fp_init 

더미 인수에서 "포인터"속성을 제거했는데 이제는 작동합니다. 왜 그래도 모르겠다.

관련 문제