2014-09-19 35 views
2

我在論壇上尋找一個解決方案,但我失敗了。我的主要問題是我太喜歡C語言和Fortran-C的互操作性,爲的是明白我在做什麼錯誤。iso_c_binding調用帶例程的Fortran指針的C例程

我想從Fortran中調用一個C例程,但是我遇到了變量聲明的問題。我舉了一個例子。

這是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_initx_final應該是指針(對吧?)。

當我嘗試編譯它時,在主程序中調用photon_trace時,在參數列表中給出了一個錯誤。

有什麼建議嗎?我正在使用gcc 4.8

P.S. gcc 4.4是否具有與iso_c_binding相同的功能,或者我需要爲使用它做不同的事情嗎?

編輯時,VLADIMIR評論:

感謝弗拉基米爾!我正在調用這個函數,因爲我在這個例子中看到它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 2014-09-19 16:08:32

+0

在 - >的參數列表中出現語法錯誤,並且它指向C_FLOAT(x_int) – Syph 2014-09-19 16:26:18

+0

我看到您混合了雙打和浮動。如果你在C中有雙打,你必須在Fortran中使用'c_double',看我的答案。它爲我工作。你也沒有指定你期望的輸出。 – 2014-09-20 10:49:19

回答

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 2014-09-20 11:06:56

+0

弗拉基米爾,你可以看看這個問題http://stackoverflow.com/questions/26740373/iso-c-binding-calling-c-routine-with-pointers-from-fortran請?我想這對你來說是微不足道的!謝謝!! – Syph 2014-11-05 15:05:55

+0

@Syph你應該使用標籤'fortran'來獲得任何fortranners的關注。 – 2014-11-05 15:36:40