2016-07-21 5 views
0

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

Он компилируется без ошибок, но при попытке запустить код, он говорит, что:

«Размерность массива„p2“(В Fortran функции) имеет степень 3 вместо -4537421815 (или какой-то другой аналогичное число) «

Я не уверен, что здесь происходит. Я приложу два кода ниже.

ПРИМЕЧАНИЕ:: Я удалил много дополнительных строк инициализации переменной, которые, как мне кажется, не нужны для поиска проблемы.

функция C:

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

extern "C" double* __multiphase_tools_MOD_project(double p1[],double *mydt,int *myi,int *myj,int *myk); 

extern "C" void cuda_(int *ptr_band, double *ptr_u, double *ptr_v, double *ptr_w) 
{ 

    double *pt_out; 
    double pt_in[3]; 


    // Loop over the domain and compute fluxes near interfaces 
    //======================================================================================= 
    // X FACE 
    //======================================================================================= 

    for (k = kmin; k <= kmax; k++) 
    { 
      for (j = jmin; j <= jmax; j++) 
      { 
       for (i = imin; i <= imax; i++) 
       { 
        if (abs(band[i-1][j][k]) <= nband_CFL && abs(band[i][j][k]) <= nband_CFL) 
        { 
         for (int n = 1; n < 10; n++) 
         { 
           pt_in[0] = pt[0][n][1]; pt_in[1] = pt[1][n][1]; pt_in[2] = pt[2][n][1]; 
           pt_out = __multiphase_tools_MOD_project(pt_in,&neg_dt_uvw,&i,&j,&k); 
         } 
        } 
       } 
      } 
    } 
    return; 
} 

Fortran Функция:

function project(p1,mydt,myi,myj,myk) result(p2) 
    use math 
    use iso_c_binding 
    implicit none 
    real(WP), dimension(3) :: p2 
    real(WP), dimension(3), intent(in) :: p1 
    real(WP),    intent(in) :: mydt 
    integer,    intent(in) :: myi,myj,myk 
    real(WP), dimension(3) :: v1,v2,v3,v4 
    v1=get_velocity(p1    ,myi,myj,myk) 
    v2=get_velocity(p1+0.5_WP*mydt*v1,myi,myj,myk) 
    v3=get_velocity(p1+0.5_WP*mydt*v2,myi,myj,myk) 
    v4=get_velocity(p1+  mydt*v3,myi,myj,myk) 
    p2=p1+mydt/6.0_WP*(v1+2.0_WP*v2+2.0_WP*v3+v4) 
    return 
    end function project 
+2

Почему бы не добавить 'bind (c)' в определение функции Fortran и избежать (что я предполагаю) ручного управления имени? Это также может вызвать проблему с вызовом. Я только что заметил: почему вы используете 'iso_c_binding', но не ссылаетесь ни на какие из них? Возможно, этот модуль не делает то, что вы думаете. – francescalus

+0

Прямо сейчас это часть большого кода fortran, который часто ссылается на эту функцию fortran. Если я добавлю к ним объекты iso_c_binding, например bind (C), будет ли он испортить функцию, когда она вызывается функциями fortran, которые уже работают хорошо? – LeeVining

+0

'bind (c)' не является сущностью 'iso_c_binding'. Это полностью отличная часть возможности взаимодействия C в Fortran. Но 'bind (c)' сам не изменяет, как Fortran видит функцию. [Он добавляет определенные ограничения, такие как совместимость аргументов, которые могут изменить ситуацию.] – francescalus

ответ

3

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

Например

function f() result(res) 
    real :: res(3) 
    res = [1.,2.,3.] 
end 

выглядит во внутреннем коде GCC, как

f (struct array1_real(kind=4) & __result) 
{ 
} 

Я предлагаю, чтобы преобразовать функцию в подпрограмму. Таким образом, вы можете точно контролировать аргумент (параметр) для массива, и вы можете сделать интерфейс C:

subroutine project(p1,p2,mydt,myi,myj,myk) bind(C) 
    real(WP), dimension(3), intent(out):: p2 
    ... 

или вы можете написать подпрограмму обертки, которая вызывает вашу функцию, чтобы сохранить Фортран функциональности без изменений.

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