2014-10-31 4 views
1

Я опубликовал аналогичный вопрос несколько недель назад (iso_c_binding calling C routine with pointers from Fortran with arrays), и я нашел решение моей проблемы. Теперь я изменил несколько вещей, и у меня снова возникли проблемы. Ниже приводится упрощенная версия моей проблемы.ISO_C_BINDING Вызов функции C из Fortran (с удвоениями и массивами)

У меня есть основная программа в Fortran:

program main_dummy 
! compile: gcc -c dummy_trace.c 
! f95 raytracing.f90 main_dummy.f90 dummy_trace.o -o main 
use, intrinsic :: ISO_C_BINDING 
use raytracing 

implicit none 

!real(kind=8) :: x_in(4), x_fin(4) 
real(C_DOUBLE), dimension(0:3) :: x_in, x_fin 
real(C_DOUBLE) :: spin 
integer :: rt_ok 

x_in = (/1,2,3,4/) 
x_fin = (/0,0,0,0/) 
spin = 0.7 

write(*,*)'x_in, x_fin before = ', x_in, x_fin 
rt_ok = photon_trace(spin,x_in,x_fin) 
write(*,*)'return rt = ', rt_ok 
write(*,*)'x_in, x_fin after = ', x_in, x_fin 


end program main_dummy 

Каких использовать подпрограмму, содержащий интерфейс для подпрограммы C:

module raytracing 
    Interface 
    integer (C_INT) function photon_trace(BHsp, x_init, x_final) & 
     bind(C, name='photon_trace') 
     use , intrinsic :: ISO_C_BINDING 
     implicit none 
     real(C_DOUBLE) :: BHsp, x_init(4), x_final(4) 
    end function photon_trace 
    end interface 
end module raytracing 

и это C рутина:

#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 
#include <complex.h> 


#undef I 


int photon_trace(double BHsp, double x_init[4], double x_final[4]) 
//*************************************************** 
{ 

    printf("BHsp %f\n", BHsp); 
    double r,m,t,phi; 

    t = x_init[0]; 
    r = x_init[1]; 
    m = x_init[2]; 
    phi = x_init[3]; 
    printf("t0 %f\n", t); 
    printf("r0 %f\n", r); 
    printf("m0 %f\n", t); 
    printf("phi0 %f\n", r); 

    t=t+1.0; 
    r=r+1.0; 
    m=m+1.0; 
    phi=phi+1.0; 

    printf("t1 %f\n", t); 
    printf("r1 %f\n", r); 
    printf("m1 %f\n", t); 
    printf("phi1 %f\n", r); 

    x_final[0] = t; 
    x_final[1] = r; 
    x_final[2] = m; 
    x_final[3] = phi; 

    return 0; 

} 

Если я скомпилирую и запустил программу, это то, что я получаю:

x_in, x_fin перед тем = 1,0000000000000000 2,0000000000000000 3,0000000000000000 4,0000000000000000 0,0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000

BHsp 0,000000

t0 0,700000

Г0 0,000000

m0 0,700000

phi0 0,000000

t1 1,700000

г1 1,000000

м1 1,700000

phi1 1,000000

возврата ВУ = 0

x_in, x_fin после = 1,6999999880790710 1,0000000000000000 1,0000000000000000 1,0000000000000000 0,0000000000000000 0,0000000000000000 0,0000000000000000 0,0000000000000000

Обратите внимание, что перед тем, как поставить переменную «вращение», все работает. Он мог читать входной массив, делать отпечаток и давать правильный вывод.

Теперь, когда я добавил переменную ths, есть некоторые проблемы для процедуры C в чтении того, что я передаю, и я не могу понять, что не так. Любое предложение?

(Обратите внимание, что в реальном случае я собираюсь передать несколько переменных, а также 2 ввода и 2 выходных массива с размером 4).

Большое спасибо заранее!

ответ

5

Изменить интерфейс:

module raytracing 
    Interface 
    integer (C_INT) function photon_trace(BHsp, x_init, x_final) & 
     bind(C, name='photon_trace') 
     use , intrinsic :: ISO_C_BINDING 
     implicit none 
     real(C_DOUBLE) :: x_init(4), x_final(4) 
     real(c_double), value :: BHsp 
    end function photon_trace 
    end interface 
end module raytracing 

Ваша функция C занимает double, а не double*, так что вы должны передать скаляр с атрибутом value так, что Fortran знает передавать по значению, а не его по умолчанию проход по ссылке.

С помощью этого небольшого изменения (и некоторые незначительные изменения в вашем C фактически напечатать значения m и phi) это выход из вашего примера кода:

% ./main 
x_in, x_fin before = 1.0000000000000000  2.0000000000000000  3.0000000000000000  4.0000000000000000  0.0000000000000000  0.0000000000000000  0.0000000000000000  0.0000000000000000  
BHsp 0.700000 
t0 1.000000 
r0 2.000000 
m0 3.000000 
phi0 4.000000 
t1 2.000000 
r1 3.000000 
m1 4.000000 
phi1 5.000000 
return rt =   0 
x_in, x_fin after = 1.0000000000000000  2.0000000000000000  3.0000000000000000  4.0000000000000000  2.0000000000000000  3.0000000000000000  4.0000000000000000  5.0000000000000000 
+0

Большое спасибо Кейси! Он работает отлично! – Syph

+0

Кейси, не могли бы вы взглянуть на эту проблему http://stackoverflow.com/questions/26740373/iso-c-binding-calling-c-routine-with-pointers-from-fortran? Наверное, это так же тривиально, как этот для вас! спасибо – Syph

Смежные вопросы