Я копал на форуме, ища решение, но мне не удалось. Моя основная проблема заключается в том, что я слишком нуб с языком 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
Что происходит Вот?
Большое спасибо за драгоценную помощь!
Какую конкретную «ошибку в списке аргументов» вы получаете? – APerson
Ошибка синтаксиса в списке аргументов при -> и он указывает C_FLOAT (x_int) – Syph
Я вижу, вы смешиваете парные и плавающие пары. Если у вас есть удвоение на C, вы должны использовать 'c_double' в Fortran., См. Мой ответ. Он работает для меня. Вы также не указали, какой результат вы ожидаете. –