Изменение массива Fortran в C

В Fortran у меня есть массив, указанный как:

dimension insv(*)

Теперь я хотел бы отредактировать этот массив из C. Мне удалось прочитать массив из C с помощью iso_c_binding:

  SUBROUTINE userroutine(insv)
  IMPLICIT NONE
  INTERFACE
  SUBROUTINE MODIFYARRAY(insv) BIND(C)
  USE, INTRINSIC::ISO_C_BINDING
     REAL(C_DOUBLE),DIMENSION(*), INTENT(INOUT) :: insv
  END SUBROUTINE MODIFYARRAY
  END INTERFACE

  dimension insv(*)

  WRITE(insv(0))
  call modifyarray(insv)
  WRITE(insv(0))
  END

Моя функция C:

__declspec(dllexport) void modifyarray(double * insv)

Но изменение значения в этом массиве в C либо приводит к сбою, либо вообще не изменяется.

__declspec(dllexport) void modifyarray(double * insv)
{
    insv[0] = 1234.00;
}

Я не уверен, что я должен изменить на iso_c_binding или функцию C, чтобы это заработало.

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


person Satchmode    schedule 15.06.2017    source источник
comment
Пожалуйста, покажите код. Особенно вся функция C. См. минимально воспроизводимый пример. И как вы это называете на Фортране, включая объявления переменных. Мы должны знать, откуда изначально взялся массив.   -  person Vladimir F    schedule 15.06.2017
comment
Если у вас нет какого-либо другого правила неявной типизации, insv является целочисленным массивом. Подпрограмма ожидает реального аргумента.   -  person francescalus    schedule 15.06.2017
comment
Изменение его на INTEGER(C_INT),DIMENSION(*) дает мне следующую ошибку: Тип фактического аргумента отличается от типа фиктивного аргумента. Я также изменил параметр функции C на: int * insv   -  person Satchmode    schedule 15.06.2017
comment
Покажите полный код. Включая implicit none и включая все объявления переменных.   -  person Vladimir F    schedule 15.06.2017
comment
Привет Владимир, это полный код, переменных больше, но они все одинаковые, неактуальные: common/bmcntc/ibmcnt(101) common/thropt/itopaz(101),iprm_thrm(20),rprm_thrm(20) common/blk03/rdumy1(2),idumy6(25),numsh12,ndtot,nsl_th,lenhsv, . numel2,numel4,numel6,numel8,numel10,numel20 dimension insv(*),areas(*),xs(*),ys(*),zs(*),lsv(*), . ix1(*),ix2(*),ix3(*),ix4(*),aream(*),xx1(nlq,*),xx2(nlq,*) . ,xx3(nlq,*),stfn(*),stf(*),fni(*),dx(*),dy(*),dz(*),ua(*)   -  person Satchmode    schedule 15.06.2017
comment
Изменить свой вопрос. В комментарии это невозможно прочитать. Начните с program, закончите end program. Создайте полный, компилируемый пример кода (минимальный воспроизводимый пример). Удалите ненужные части кода, но протестируйте сокращенный код, прежде чем публиковать его здесь.   -  person Vladimir F    schedule 15.06.2017
comment
И не забывайте implicit none.   -  person Vladimir F    schedule 15.06.2017
comment
Привет, владимир, проблема в том, что я не могу опубликовать полную программу, так как она является частью более крупной программы. Я просто пишу расширение, так сказать, которое использует и модифицирует массивы пользовательских подпрограмм в нашей логике C DLL. Также я не могу использовать неявный none. компиляция затем дает мне ошибки: это имя не имеет типа и должно иметь явный тип.   -  person Satchmode    schedule 15.06.2017
comment
Я говорю, создайте программу, которую мы сможем протестировать. Это не обязательно должен быть весь код, который у вас есть. Никто не хочет видеть тысячи строк кода. Мы хотим видеть полный компилируемый код, который вы создаете, выбирая важные элементы из своего большого кода. Эта программа ДОЛЖНА воспроизвести проблему и должна быть скомпилирована нами. Вы уже прочитали минимальный воспроизводимый пример или я просто зря публикую ссылку?   -  person Vladimir F    schedule 15.06.2017
comment
Подпрограмма, которую вы опубликовали сейчас, не является законной для Фортрана. Он не будет компилироваться. Проверьте код, прежде чем вставлять его сюда! Он должен быть компилируемым и должен воспроизводить проблему. Очень важно прочитать минимально воспроизводимый пример.   -  person Vladimir F    schedule 15.06.2017


Ответы (1)


При условии, что:

  • insv представляет собой массив real(C_DOUBLE)
  • вы хотите записать insv (а не в файловую единицу, определенную insv, как сейчас кажется)
  • вызывающая программа определяет insv как массив из 10 компонентов

возможный рабочий тестовый пример:

Фортран:

SUBROUTINE userroutine(insv)
    USE, INTRINSIC::ISO_C_BINDING
    IMPLICIT NONE
    INTERFACE
        SUBROUTINE MODIFYARRAY(insv) BIND(C)
            USE, INTRINSIC::ISO_C_BINDING
            REAL(C_DOUBLE),DIMENSION(*), INTENT(INOUT) :: insv
        END SUBROUTINE MODIFYARRAY
    END INTERFACE

    real(C_DOUBLE), dimension(*) :: insv

    WRITE(*,*) insv(1)
    call modifyarray(insv)
    WRITE(*,*) insv(1)
END

PROGRAM MAIN
    USE, INTRINSIC::ISO_C_BINDING
    real(C_DOUBLE) :: insv(10)
    insv = 2.d0
    call userroutine(insv)
END

C:

void modifyarray(double * insv)
{   
    insv[0] = 1234.00;
}   
person Franz    schedule 15.06.2017
comment
Здравствуйте, Франц, ваш тестовый пример дал мне представление о том, в чем проблема. В Fortran индекс массива начинается с 1, тогда как C начинается с 0. Я менял неправильный индекс на стороне C. Спасибо большое. - person Satchmode; 15.06.2017
comment
На стороне Fortran, а не на стороне C. По крайней мере, в неполном коде, который вы показываете. - person Vladimir F; 15.06.2017