Каков эквивалентный тип в C для REAL (KIND = real_normal) в Fortran? - PullRequest
2 голосов
/ 19 июля 2010

У меня проблема с передачей массива из Фортрана в функцию c: В Фортране массив определен как

REAL(KIND=real_normal) , DIMENSION(:), ALLOCATABLE :: array
call cFunc(array)

Если определить cFunc как

void cFunc(double *data){...}

Чем данные содержат только «мусорные» значения. Где проблема в этом случае? (с целыми числами хорошо работает это решение).

ТНХ. РЕДАКТИРОВАТЬ: Моя платформа: Компилятор: VS 2008, версия Intel Compiler 11 ОС: Win7

РЕДАКТИРОВАТЬ 2: Я определяю интерфейс для c-функции следующим образом (код сводится к одному элементу, что создает проблемы, у реальной функции больше параметров):

interface c_interface

subroutine cFunc(array) bind (C, name = "cFunc")
use iso_c_binding
REAL(c_double), DIMENSION(*)::array
end subroutine cFunc

Памяти в фортране выделяется

ALLOCATE (array(numberOfElements))
call cFunc(array)

В данный момент я получаю ошибку времени выполнения "Переполнение с плавающей точкой". В некоторых случаях массив правильных элементов.

Ответы [ 4 ]

4 голосов
/ 19 июля 2010

Фрагмент REAL(KIND=real_normal) не является полной и стандартной спецификацией типа данных.Где-то в вашем источнике должно быть объявление переменной real_normal.Я предполагаю, что он объявлен так, что array это 4- или 8-байтовые числа с плавающей запятой, но это только предположение.То, что array не является массивом чисел с плавающей запятой по умолчанию (называемых Fortran) real.

Как предложил один из других ответчиков, исследуйте совместимость с C особенности Fortran 2003. Если ваш компилятор не реализует их, отбросьте его и получите компилятор, который это делает.

2 голосов
/ 19 июля 2010

@ High Performance Mark предлагает очень хорошие рекомендации, и я настоятельно рекомендую ISO_C_Binding в Fortran 2003 (поддерживаемый многочисленными компиляторами Fortran) для обеспечения взаимодействия между Fortran и C - здесь есть большая проблема, которая делает ISO_C_Binding более полезной: Fortran Распределяемые массивы являются более сложными, чем обычные массивы. Если вы «взломаете его» и напрямую передадите указатель на код C, вы, скорее всего, передадите указатель на внутреннюю структуру Фортрана, описывающий размещаемый массив, а не указатель на последовательность числовых значений. Выделенные массивы напрямую не поддерживаются ISO_C_Binding, но должны работать, если вы пишете интерфейс ISO_C_Binding (в отличие от того, что я написал изначально) - в книге «Фортран 95/2003 объяснил» говорится, что компилятор распознает вызванную подпрограмму t получает размещаемый массив и выполняет копирование / копирование в соответствии с массивами.

P.S. Я предполагаю, что копирование / копирование не должно быть необходимым для простого размещаемого фактического аргумента. Когда компилятор распознает через явный интерфейс (который может быть интерфейсом ISO_C_Binding), что фиктивный аргумент вызываемой подпрограммы не является размещаемым, компилятор должен просто иметь возможность извлечь указатель на фактический массив из описания выделяемого и передать это в качестве аргумента. В некоторых случаях потребуется копирование / копирование, например указатель на несмежный массив, например указатель с шагом, не равным единице (например, указатель, указывающий на элементы 1, 3, 5, .. .). Но без какого-либо интерфейса компилятор, скорее всего, передаст дескриптор выделяемого массива, который не будет тем, что ожидает C ....

0 голосов
/ 19 июля 2010

Является ли real_normal 32-битной или 64-битной плавающей точкой?Что произойдет, если вы объявите функцию как void cFunc(float*data)?

0 голосов
/ 19 июля 2010

REAL может по умолчанию REAL*4, в этом случае вы хотите float* вместо double*.

Также убедитесь, что вы создаете прототип функции перед ее использованием, в противном случае C имеет тенденцию автоматически повышать float s до double s при отсутствии причины не делать этого.И убедитесь, что вы не берете double, а затем берете его адрес и передаете его как float*.

...