Передача целочисленного массива Fortran в подпрограмму C, только первый переданный элемент

Я пытаюсь передать целочисленный массив из Fortran в C, но могу передать только первый элемент массива.

У меня есть тестовая программа ниже, которая воспроизводит ошибку. Где я ошибаюсь?

program test
   use foo

   integer (kind=c_int), allocatable :: hgmu_dose(:)
   allocate (hgmu_dose(0:10))

HGMU_dose(0)=22
HGMU_dose(1)=2
HGMU_dose(2)=3
HGMU_dose(3)=4
HGMU_dose(4)=5
HGMU_dose(5)=6
HGMU_dose(6)=7
HGMU_dose(7)=8
HGMU_dose(8)=9
HGMU_dose(9)=10
HGMU_dose(10)=11

print *, "HGMU_dose=", hgmu_dose 

call  test_interface(hgmu_dose)

end program

module foo
  use ISO_C_Binding 

  implicit none 
  interface  
    subroutine test_interface(dose) bind(C,name="INTERFACE")
      import :: c_int
      import :: c_double
      import :: c_char

      integer (kind=c_int), allocatable :: dose(:)
    end subroutine  
  end interface

end module foo 

С участием

#include "interface.h"

 namespace interface
{

  extern "C" void INTERFACE (int dose[NDIM])
  {
    for (int i = 0; i < NDIM; i++)
      cout << " dose[" << i << "] = " << dose[i] << endl;
  }
}

person ronnie    schedule 10.03.2014    source источник
comment
Не могли бы вы показать использование interface.h или, по крайней мере, где определено NDIM?   -  person Timothy Brown    schedule 11.03.2014


Ответы (1)


Здесь есть несколько проблем.

Первый — в вашем определении интерфейса test_interface. Вам не нужно ключевое слово allocatable.

subroutine test_interface(dose) bind(C,name="INTERFACE")

  import :: c_int

  integer (kind=c_int) :: dose(:)

end subroutine

Во-вторых, iso_c_binding будет передаваться по ссылке. Поэтому, когда вы определяете свою функцию в C, она должна принимать указатель на массив:

void INTERFACE (int *dose[NDIM])

Наконец, в качестве примечания, вам не нужно определять свой массив Fortran как начинающийся с 0. Вы можете использовать Fortran обычно, начиная с 1.

person Timothy Brown    schedule 10.03.2014
comment
Объявление C в порядке - это просто выделяемый атрибут в блоке интерфейса fortran, который проблематичен. - person IanH; 11.03.2014
comment
@IanH ты уверен? Поскольку это не то, что я вижу. Когда int dose[NDIM] cout дает мне dose[0] = -1581234144, dose[1] = 32712 и т. д. Если я передаю его как int *dose[NDIM], а затем печатаю с помощью (*dose)[i], я получаю правильные значения dose[0] = 22, dose[1] = 2 - person Timothy Brown; 11.03.2014
comment
Я уверен. Также обратите внимание, что фиктивный аргумент в интерфейсе Fortran также не может принимать форму — вам нужно изменить спецификацию массива с (:) на (*) или, если значение NDIM доступно на стороне Fortran, на (NDIM). (Более поздние стандарты, чем F2008, могут разрешать такие вещи, как отложенная форма и аргументы предполагаемой формы, но тогда есть существенные изменения в том, что должен делать код C.) - person IanH; 12.03.2014
comment
спасибо за ваши комментарии - у меня есть тестовый пример, работающий для полного набора параметров, которые мне нужно передать из фортрана, но когда я использую тот же код в моем гораздо большем и более сложном коде, он падает с ошибкой нарушения доступа - один из моих избранное. Я хотел опубликовать полный тестовый пример здесь, но он не позволил мне. - person ronnie; 14.03.2014
comment
исправил мою проблему! - в Visual Studio была настройка, определяющая, передаются ли длины строк сразу после строки или в конце списка аргументов - у меня была неправильная настройка - person ronnie; 14.03.2014