Сделать внешние функции доступными для других функций/модулей в Fortran

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

Я пишу на интерфейсе, который обращается к Fortran DLL из С#.

module csWrapper
  interface
    subroutine vdiTestFuncCllBak(inputValue, retValue)
      INTEGER, INTENT(IN) :: inputValue
      INTEGER, INTENT(INOUT) :: retValue      
    end subroutine
  end interface

  procedure(vdiTestFuncCllBak), pointer :: m_vdiTestFuncCllBak
end module csWrapper

module VdiFunctionRunnerMain
  use csWrapper
  implicit none

  contains       
    integer function VdiFunctionRunner (XTGA, ARRAY_810, vdiCwertCllbak, vdiIwertCllbak, vdiRwertCllbak, vdiCwert2Cllbak, vdiIwert2Cllbak, vdiRwert2Cllbak, vdiErsterCllBak, vdiLetzterCllBak, vdiTestFuncCllBak)
      !DEC$ ATTRIBUTES DLLEXPORT ::VdiFunctionRunner
      !DEC$ ATTRIBUTES REFERENCE :: XTGA, ARRAY_810, vdiCwertCllbak, vdiIwertCllbak, vdiRwertCllbak, vdiCwert2Cllbak, vdiIwert2Cllbak, vdiRwert2Cllbak, vdiErsterCllBak, vdiLetzterCllBak, vdiTestFuncCllBak
      implicit none      
      external vdiCwertCllbak, vdiIwertCllbak, vdiRwertCllbak, vdiCwert2Cllbak, vdiIwert2Cllbak, vdiRwert2Cllbak, vdiErsterCllBak, vdiLetzterCllBak, vdiTestFuncCllBak

      !procedure(vdiErsterCllBak), pointer :: m_vdiErsterCllBak
      CHARACTER (len=256) XTGA
      CHARACTER (len=256) TGA, ARRAY_810(10), retValue, satzArt, satzArt2
      CHARACTER (len=256) :: cWertCallBackRet

      integer :: nrReturnValues = 1

      m_vdiTestFuncCllBak => vdiTestFuncCllBak

      call vdiTestFuncCllBak(nrReturnValues, nrReturnValues)
      call m_vdiTestFuncCllBak(1, nrReturnValues)

      VdiFunctionRunner = nrReturnValues
    end function VdiFunctionRunner

end module VdiFunctionRunnerMain

Поскольку коду Fortran нужна возможность использовать некоторые функции кода C#, необходимо передать два делегата в код Fortran (vdiCwertCllbak, vdiIwertCllbak).

Это работает довольно хорошо, когда они используются в MainFunction, так что интерфейс работает до сих пор.

Теперь необходимо, чтобы c#-функции были доступны из других функций вне MainFunction и даже в разных модулях.

Я пытался использовать указатели функций для решения этой проблемы, но всегда получаю следующую ошибку при вызове m_vdiTestFuncCllBak. Вызов vdiTestFuncCllBak работает без проблем.

Такое же поведение при инициализации указателя в функции или во внешнем модуле.

Вызывается следующий код С#:

private void vdiTestFunc(ref int inputValue, ref int retValue)
{
  retValue = inputValue + 1;
  return;
}

Проблема в том, что ссылки inputValue и retValue не устанавливаются при использовании funtionpointer.

У кого-то была такая же проблема раньше, и он знает возможное решение или имеет ссылку с помощью? Я не нашел информации об этом в моих поисках.

Я использую компилятор Intel 11.

Помощь очень ценится.


person thomacco    schedule 24.10.2011    source источник


Ответы (1)


Быстрым и грязным способом было бы создать модуль с указателем на процедуру:

module callback_module
    procedure(),pointer::p
end module

integer function MainFunction(XTGA, ARRAY_810, vdiCwertCllbak, vdiIwertCllbak)
  !DEC$ ATTRIBUTES DLLEXPORT ::MainFunction
  !DEC$ ATTRIBUTES REFERENCE :: XTGA, ARRAY_810, vdiCwertCllbak, vdiIwertCllbak
  use callback_module
  implicit none

  external vdiCwertCllbak, vdiIwertCllbak
  integer :: nrReturnValues = 1
  integer :: iWertCallBackRet = 12
  satzArt = '710.10' // char(0)

  p=>vdiIwertCllbak
  call vdiIwertCllbak(satzArt, 1, 2, iWertCallBackRet)

  MainFunction= nrReturnValues
end function MainFunction

integer function tga_810(xtga,array_810)  
  use callback_module
  character(len=256) xtga,tga,array_810(4),s, caption, inputBox

  call p('710' // char(0), 1, 2, retValue)

  tga_810 = 1
end function tga_810

РЕДАКТИРОВАТЬ:

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

module callback_module
    interface
        subroutine callback_sub(arg1,arg2,...)
            !Declare all arguments as they appear in the actual callback routine
        end subroutine
    end interface

    procedure(callback_sub),pointer::p
end module

Вам нужно будет правильно определить аргументы процедуры для интерфейса.

Это также может быть вызвано наличием необязательных аргументов. Есть ли у vdiIwertCllbak опции?

person bdforbes    schedule 24.10.2011
comment
Спасибо за предложение. Я пытался использовать для этого указатели функций, но получаю AccesViolationError, когда пытаюсь получить доступ к указателю функции. Я обновлю свой вопрос :) - person thomacco; 25.10.2011
comment
Спасибо, я сделал это так, и ошибка AccessViolationError теперь исправлена ​​​​для моей testFunction, которая имеет только 2 целочисленных параметра. Я предполагаю, что проблема была в том, что указатель не был связан с интерфейсом. Но теперь я получаю ссылку на объект, а не экземпляр объекта. Я обновлю свой вопрос. Спасибо за помощь. - person thomacco; 03.11.2011
comment
Нет, у меня нет необязательных аргументов. Всего два целых числа. - person thomacco; 04.11.2011
comment
Боюсь, я не слишком хорошо знаком с C# и тем более не смешиваюсь с Fortran. Надеюсь, кто-то еще это увидит и ответит. - person bdforbes; 05.11.2011