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
14.0.2를 사용하고 있습니까? – IanH
14.0.1을 사용하여 업데이트 중입니다. @IanH – Exascale
14.0.2에서 BIND (C) 함수에 대한 포인터를 VALUE에 전달하는 것과 관련된 버그 수정이있었습니다. http://software.intel.com/en-us/forums/topic/498635를 참조하십시오. – IanH