Access Violation: Forrtran application to DLL in 32bit windows

Access Violation: Forrtran application to DLL in 32bit windows

I have encountered trouble with a 32-bit application developed with ifort. I have an executable (created in Fortran) that calls a dll (created in C++). The specific error I get at run-time is:

forrtl: severe (157): Program Exception - access violation

I have a feeling my problem spawns from how I call the DLL, or at least something to do with the !DEC$ attributes. I can sucessfully compile and run the program in linux using another compiler, but I am encoutering this trouble when porting it to windows. I call the DLL using these directives:

SUBROUTINE MAP_C2F_CopyInput( InputData, ErrStat, ErrMsg )
  TYPE(MAP_inputtype), INTENT(INOUT) :: InputData
  INTEGER(IntKi), INTENT( OUT) :: ErrStat
  CHARACTER(*), INTENT( OUT) :: ErrMsg
  INTEGER(IntKi) :: i
  ErrStat = ErrID_None
  ErrMsg = ""
  IF ( ALLOCATED( InputData%X ) ) THEN
    i1 = SIZE(InputData%X,1)
    CALL MAP_C2F_Input_X(InputData%C_obj,InputData%X ,i1)
    #if defined(IVF_DLL_CALL_DIRECTIVE)
      !DEC$ ATTRIBUTES STDCALL::MAP_C2F_Input_X
      !DEC$ ATTRIBUTES ALIAS:'_map_c2f_input_x_@12'::MAP_C2F_Input_X
      !DEC$ ATTRIBUTES DLLIMPORT::MAP_C2F_Input_X
    #endif
 ENDIF

...

END SUNROUTINE ...

Any help pointing out to what I've done wrong would be appreciated. 

Thanks,

M

5 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Please show the declaration of the function in C++.

Do you control the source of the C++ DLL?  If so, why use stdcall?  For new code today use BIND(C), etc, and then the code for Linux and Windows can be the same and portable to other Fortran processors/C compilers.  Plus you'll have more street cred in the Fortran 'hood.

ISO_C_Binding is a good feature to use. And we do use ISO C Binding for the parts of the code were we can; but this question originates from a portion of the code that is auto-generated, and there much flexibility here. I do control both the C and fortran source code. This is the C call declaration:

#ifdef _WIN32 //define stuff for Windows (32-bit)
  #include "stdbool.h"
  #define CALL __declspec( dllexport )
  #define STDCLL __stdcall
#elif _WIN64 //define stuff for Windows (64-bit) (not yet supported)
  #include "stdbool.h"
  #define CALL __declspec( dllexport )
  #define STDCLL __stdcall
#else //gcc
  #include <stdbool.h>
  #define CALL
  #define STDCLL
#endif

...

CALL void STDCLL map_c2f_input_x_ ( MAP_InputType_t *src , double *dst , int *n1 )
{
  int i1 ;
  double *p ;
  p = (double *)src->X ;
  for (i1 = 0 ; i1 < *n1 ; i1++ )
  {
    dst[i1] = *p++ ;
  }
}

The n1 argument is by reference (it is a pointer) in the C++ definition, but it is (implicitly) by value in the Fortran as a consequence of the STDCALL attribute.  Perhaps provide a complete interface block for the function that lays the complete interface out (along with ATTRIBUTES REFERENCE for the relevant argument).  This is good practice anyway.

I'd be very strongly inclined to sit down and have a good chat to the code generator.  Fixing it is going to make everyone's life easier.  Just define STDCLL as "nothing" for all cases, obliterate the trailing underscore (or add that to the binding label in Fortran) and then add the appropriate interface body with BIND(C) on the Fortran side.

(ISO_C_BINDING is just a module, it doesn't have any special powers (though some of the procedures it provides are special).  BIND(C) and use of VALUE is really where the magic happens.  I mention this because the (unfortunate, IMHO) focus on the module tends to distract from the real significance of the C interoperability features of F2003.  The problems you describe in this thread are classic examples in that regard.)

>>>>... for ( i1 = 0 ; i1 < *n1 ; i1++ )
>>...
>>...The n1 argument is by reference ( it is a pointer) in the C++ definition...

Take into account that a star character * is used before n1. The for-loop should do iterations until i1 is less then a value stored at n1 address. Try to verify that value in the debugger and if debugging is Not possible simply display that value with a MessageBox Win32 API function.

Leave a Comment

Please sign in to add a comment. Not a member? Join today