Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Callback from Visual Studio c++ code to Fortran (CVF) DLL fail

Chris_O_1
Beginner
1,198 Views

Hi, I want to develope an interface that will make a callback from visual studio 2005 c++ to Fortran (CVF) dll function to echo the calcualtion progress.

Below are my testing codes:

Fortran DLL code:

!  Cb1.f90
!
!  FUNCTIONS/SUBROUTINES exported from Cb1.dll:
! Cb1      - subroutine
!


module GUI_OLI
    implicit none
    save
    interface
     integer function GUI_FCALL(PROG)
        REAL*8  :: PROG
      end function
    end interface
    pointer (p_GUI_FCALL, GUI_FCALL)
end module GUI_OLI

subroutine CONV ()

  ! Expose subroutine Cb1 to users of this DLL
  !
  !DEC$ ATTRIBUTES DLLEXPORT::CONV
  USE GUI_OLI
  IMPLICIT NONE
  INTEGER i,j
  REAL*8  m

  IF(p_GUI_FCALL .ne. 0) THEN
   DO i = 1, 100
     m = i
  j = GUI_FCALL(m)
   END DO
  END IF

end subroutine CONV


subroutine SETCALLBACKFUN (FCALL)

  ! Expose subroutine Cb1 to users of this DLL
  !
  !DEC$ ATTRIBUTES DLLEXPORT::SETCALLBACKFUN

      USE GUI_OLI
      IMPLICIT NONE
      INTEGER(INT_PTR_KIND()) :: FCALL
 
      p_GUI_FCALL = FCALL
     
end subroutine SETCALLBACKFUN

visual studio 2005 c++ code:

extern "C" {
 void _stdcall SETCALLBACKFUN(void* progress);
 void _stdcall CONV();
}
double g_dProgress;

void _stdcall Progress(double dPer)
{
 g_dProgress = dPer;
 return dPer;
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
 int nRetCode = 0;

 ...

 SETCALLBACKFUN(Progress);
 CONV();
 int j = 0;

 ...

 return nRetCode;
}

When I debug to CONV() in c++ code. The visual studio crashs. I am not so familar with Fortran, can anyone help me find out what is the reason?

Thanks.

 

Regards

Chris

0 Kudos
6 Replies
Lorri_M_Intel
Employee
1,198 Views

Fortran passes arguments by reference; C passes them by value.

In your interface to GUI_FCALL, add

     !dec$ attributes value :: prog

and see if that helps.   That tells Fortran that the argument should be passed by value.

0 Kudos
Michael_Roberts
New Contributor I
1,198 Views

Hi Chris,

I recently asked a similar question, although from C# rather than C++, in the forum: http://software.intel.com/en-us/forums/topic/391002.

Hopefully it is of some help to you,

Michael

0 Kudos
Chris_O_1
Beginner
1,198 Views

Hi, Lorri Menard, I make changes accordingly, but it still dosen't work.

Hi, Michael, It seems I cannot use PROCEDURE declare in my CVF code, and have to use Pointer instead. Do you have suggestions for using pointer instead. I guess the clash may be caused by the use of pointer for the callback fucntion,but don't know hoe to make it. Thanks.

Chris 

0 Kudos
Lorri_M_Intel
Employee
1,198 Views

I no longer have a CVF installation available so I can't confirm this with CVF, but ... I used Intel Fortran and was finally able to create a runable program based on your code.

A couple of things to note:  you've declared Progress as a "void", yet return a double (probably ignored by the C compiler), and then store it into a Fortran integer.  I changed the return to an int.  

If you really want to return a double, please check the CVF documentation on Mixed Language Programming to see if this return type requires a hidden argument.   It most likely does not, but please check because if it does, you'll need to add that to your Progress routine.

And, if you do want to return a double, please make sure you declare the interface appropriately in the Fortran program too.

The final magic: also add a !dec$ attributes value :: fcall    in SUBROUTINE SETCALLBACKFUN(FCALL)

          Good luck!!

                             --Lorri

0 Kudos
Chris_O_1
Beginner
1,198 Views

Hi, Lorri,

It works now. Thanks a lot for your help. But I still have two problems. First,it works too slow. when i set the callback loop to 2 as

DO i = 1, 2

m = i

j = GUI_CALL(m)

END DO

it take more than half a minute to come back to C. Second, it cannot step into Progress function in C, and only updates the value of g_dProgrss to 2 after it come back to C. That is not I want. What I want is for each i value that puts in the callback, I can see the value of g_dProgrss is updated and in a faster way, in this way, I can update the progress bar accordingly. This can be achieved easily in the callback of C calling C or Fortran calling Fortran.

It is very appreciated If you can give some suggestions for it. Thanks.

 

Chris

0 Kudos
Chris_O_1
Beginner
1,198 Views

The code works fine. Thanks a lot for the help :-)

Chris

0 Kudos
Reply