0

I am new in Fortan and have a question regarding using make callback-functions available for the whole fortran-code.

I am writing on a interface which accesses a Fortran DLL from C#.

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

Because the Fortran-code need the possibility to use some functions of the C#-code to, a pass two delegates to the Fortran-code (vdiCwertCllbak, vdiIwertCllbak).

This works quite well when they are used in the MainFunction, so the interfacing works so far.

Now it is needed, that the c#-functions must be available from other functions outside of the MainFunction and even in different modules.

I tried to use functionpointers to deal with this problem, but always get the following error when calling m_vdiTestFuncCllBak. Calling vdiTestFuncCllBak works without problems.

It is the same behaviour when initializing the pointer in the function or in an external module.

The following c# code is called:

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

The problem is, that the references of inputValue and retValue are not set when using the funtionpointer.

Does someone had the same issue before and knows a possible solution or has a link with help? I haven't found information about that in my searches.

I am using the Intel 11 compiler.

Help is very much appreciated.

thomacco
  • 181
  • 2
  • 13

1 Answers1

2

A quick and dirty way would be to make a module that has a procedure pointer in it:

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

EDIT:

The access violation might be because the pointer has no associated interface.

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

You'll need to correctly define the procedure arguments for the interface.

It might also be caused by having optional arguments. Does vdiIwertCllbak have optionals?

bdforbes
  • 1,486
  • 1
  • 13
  • 31
  • Thanks for the suggestion. I tried to use functionspointers for that but get a AccesViolationError when I try to access a function pointer. I will update my question :) – thomacco Oct 25 '11 at 13:58
  • Thanks, I have done it like that and the AccessViolationError is fixed now for my testFunction, which only has 2 integer-parameters. I guess the problem was, that the pointer was not associated with an interface. But Now I get a Object reference not set an instance of an object. I will update my question. Thanks for the help. – thomacco Nov 03 '11 at 13:29
  • No, I have no optional arguments. Only two integers. – thomacco Nov 04 '11 at 10:33
  • I'm afraid I'm not too familiar with C#, and especially not mixing with Fortran. Hopefully someone else will see this and have an answer. – bdforbes Nov 05 '11 at 03:11