2014-09-19 3 views
2

Я копал на форуме, ища решение, но мне не удалось. Моя основная проблема заключается в том, что я слишком нуб с языком C и совместимостью Fortran-C, чтобы понять, что я делаю неправильно.iso_c_binding вызов подпрограммы C с указателями из Fortran с массивами

Я хочу вызвать подпрограмму C из Fortran, но у меня возникла проблема с объявлением переменных. Я сделал пример.

Это C рутина:

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

#undef I 


int photon_trace(double x_init[4], double x_final[4]) 
//*************************************************** 
{ 
double r,m,t,phi; 

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

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

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

return 0; 

} 

Это основная программа в Fortran:

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

implicit none 

real(C_FLOAT), dimension(0:3) :: x_in, x_fin 

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


write(*,*)'x_in, x_fin before = ', x_in, x_fin 
call photon_trace(C_FLOAT(x_in),C_FLOAT(x_fin)) 
write(*,*)'x_in, x_fin after = ', x_in, x_fin 


end program main_dummy 

И это модуль с интерфейсом:

module raytracing 
    Interface 
    integer (C_INT) function photon_trace(x_init, x_final) & 
     bind(C, name='photon_trace') 
     use , intrinsic :: ISO_C_BINDING 
     implicit none 
     type (c_ptr), value :: x_init, x_final 
    end function photon_trace 
    end interface 
end module raytracing 

По парень, который дал мне рутину в C, x_init и x_final должен быть указатели (справа?).

Когда я пытаюсь скомпилировать его, он дает мне ошибку в списке аргументов, когда я вызываю photon_trace в основной программе.

Любые предложения? Я использую gcc 4.8

P.S. Имеет ли gcc 4.4 те же возможности по отношению к iso_c_binding, или мне нужно будет сделать что-то другое для его использования?

EDIT ПОСЛЕ ВЛАДИМИРА COMMENT:

Спасибо Владимир! Я вызывал функцию, потому что видел это на этом примере. https://stackoverflow.com/tags/fortran-iso-c-binding/info

Я внесла модификацию, которую вы предложили, и она компилируется прямо сейчас! Проблема в том, что подпрограмма C работает с адресом переменных, а не с самими переменными.

Я положил некоторую печать в подпрограмме C:

int photon_trace(double x_init[4], double x_final[4]) 
//*************************************************** 
{ 
    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; 

} 

, а также в главном:

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_FLOAT), dimension(0:3) :: x_in, x_fin 
integer :: rt_ok 

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


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


end program main_dummy 

и то, что на экране:

x_in, x_fin before = 1.00000000  2.00000000  3.00000000  4.00000000   0.00000000  0.00000000  0.00000000  0.00000000  

t0 2.000000 
r0 512.00
m0 2.000000 
phi0 512.00

t1 3.000000 
r1 513.00
m1 3.000000 
phi1 513.00
return rt =   0 

x_in, x_fin after = 1.00000000  2.00000000  3.00000000  4.00000000  1.00000000  2.12500000  3.00000000  4.00097656  

Что происходит Вот?

Большое спасибо за драгоценную помощь!

+0

Какую конкретную «ошибку в списке аргументов» вы получаете? – APerson

+0

Ошибка синтаксиса в списке аргументов при -> и он указывает C_FLOAT (x_int) – Syph

+0

Я вижу, вы смешиваете парные и плавающие пары. Если у вас есть удвоение на C, вы должны использовать 'c_double' в Fortran., См. Мой ответ. Он работает для меня. Вы также не указали, какой результат вы ожидаете. –

ответ

4

Не переутомляйте его. Не пропустите указатели, но передайте массивы по ссылке

Кроме того, функция должна использоваться в выражении, а не в операторе вызова.

module raytracing 
    Interface 
    integer (C_INT) function photon_trace(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) 
    end function photon_trace 
    end interface 
end module raytracing 

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

implicit none 

real(c_double), dimension(0:3) :: x_in, x_fin 
integer ie 

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


write(*,*)'x_in, x_fin before = ', x_in, x_fin 
ie = photon_trace(x_in,x_fin) 
write(*,*)'x_in, x_fin after = ', x_in, x_fin 


end program main_dummy 

В совместимых процедур C Fortran передает указатели на переменные, если вы не используете value. Это называется пройти по ссылке.

> gfortran ray.c ray.f90 
> ./a.out 
x_in, x_fin before = 1.0000000000000000  2.0000000000000000  3.0000000000000000  4.0000000000000000  0.0000000000000000  0.0000000000000000  0.0000000000000000  0.0000000000000000  
x_in, x_fin after = 1.0000000000000000  2.0000000000000000  3.0000000000000000  4.0000000000000000  2.0000000000000000  3.0000000000000000  4.0000000000000000  5.0000000000000000 

P.S. gcc 4.4 очень старый, но теоретически он знает материал C interop. Попробуйте, и вы увидите.

+0

Спасибо! Это работает и для меня :) – Syph

+0

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

+0

@Syph Вы должны использовать тег 'fortran', чтобы привлечь внимание fortranners. –

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