- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In XE2016, this code works for me, so that I can then load and call the relevant function out of a DLL: ABSTRACT INTERFACE Subroutine DragCoeff_int(Reynolds, Sphericity, Value, Units) !DEC$ ATTRIBUTES STDCALL, ALIAS:'DragCoeff_int' :: DragCoeff_int !DEC$ ATTRIBUTES REFERENCE :: Units IMPLICIT NONE Real(KIND=KIND(0D0)), INTENT(IN), DIMENSION(1) :: Reynolds, Sphericity Real(KIND=KIND(0D0)), INTENT(OUT), DIMENSION(1) :: Value Character(LEN=20), INTENT(INOUT) :: Units End Subroutine DragCoeff_int END INTERFACE PROCEDURE(DragCoeff_int), pointer :: DragCoeff_F NAME = "DragCoeff_F" Reynolds = 0.7083D0; Sphericity = 0.90D0; Expected = 57.35006 p_USERFUNC = getprocaddress(hModule=dll_handle, lpProcName=TRIM(NAME)//C_NULL_CHAR) if (p_USERFUNC == NULL) then Write(*,*) "Function not found: "//TRIM(NAME) NumTest = NumTest + 1 ELSE CALL C_F_PROCPOINTER(TRANSFER(p_USERFUNC, C_NULL_FUNPTR), DragCoeff_F) CALL DragCoeff_F(Reynolds, Sphericity, Value, Units) END IF
XE2017 objects to the !DEC$ statements. What do I need to do to make my code compliant with XE2017? I have used this technique 100's of tmes in my application, so changing this is going to be a major job.
Thanks,
David
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I should note that my code is similar to the DynamicLoad example, where the comments state that the !DEC$ ATTRIBUTES directive will be required where STDCALL is used, which is the case for my DLL, since it is called from VBA as well.
XE2017 does not permit this directive.
[On a separate issue - the forum would not let me edit my post, reporting Access Denied]
David
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I tried your code and found the error message by 17.0 is against the "ALIAS" attribute.
For a procedure pointer get assigned by calling "getprocaddress" it doesn't need such an attribute in the abstract interface declaration.
Thanks,
Xiaoping Duan
Intel Customer Support
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The forum doesn't allow edits of post #1 which has been the case for a long time....
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Aliases are appropriate for actual procedures, not for abstract interfaces. A procedure is a specific instance of the class of possible procedures with the interface as declared in the abstract interface, so the ALIAS clause could be specified in a directive for DragCoeff_F, but not for the abstract interface DragCoeff_Int.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Right - it was a bug to accept ALIAS in an ABSTRACT INTERFACE. We fixed the bug.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear All,
I'm facing a similar problem with ABSTRACT INTERFACE in XE2017 using Visual Studio 2015 Community Ed.
I need to recompile a code that was originally compiled with Visual Studio 2013 Community Ed with Intel Visual Fortran Composer XE 2013 SP1.
The compiler gives me error in the 3 lines (25, 38, 56) where there is the attribute ALIAS. Having read this topic, I removed it from those 3 lines but then it gives me error in the same lines telling me that the other attributes are not valid.
MODULE OrcaFlexInterface USE NWTC_Library USE NWTC_LAPACK USE OrcaFlexInterface_Parameters USE OrcaFlexInterface_Types USE, INTRINSIC :: ISO_C_Binding IMPLICIT NONE PRIVATE ABSTRACT INTERFACE ! These are interfaces to the DLL #ifdef __GFORTRAN__ SUBROUTINE OrcaFlexUserPtfmLdInitialise(DT,TMax) BIND(C) #else SUBROUTINE OrcaFlexUserPtfmLdInitialise(DT,TMax) !!!BIND(C) #endif USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_FLOAT !DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE, ALIAS:'OrcaFlexUserPtfmLdInitialise'::OrcaFlexUserPtfmLdInitialise !GCC$ ATTRIBUTES STDCALL :: OrcaFlexUserPtfmLdInitialise REAL(C_FLOAT), INTENT(IN ) :: DT REAL(C_FLOAT), INTENT(IN ) :: TMax END SUBROUTINE OrcaFlexUserPtfmLdInitialise #ifdef __GFORTRAN__ SUBROUTINE OrcaFlexUserPtfmLd( X, XD, ZTime, DirRoot, PtfmAM, PtfmFt) BIND(C) #else SUBROUTINE OrcaFlexUserPtfmLd( X, XD, ZTime, DirRoot, PtfmAM, PtfmFt) !!!BIND(C) #endif USE, INTRINSIC :: ISO_C_Binding, ONLY: C_FLOAT, C_CHAR !DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE, ALIAS:'OrcaFlexUserPtfmLd'::OrcaFlexUserPtfmLd !GCC$ ATTRIBUTES STDCALL :: OrcaFlexUserPtfmLd CHARACTER(KIND=C_CHAR), INTENT(IN ) :: DirRoot REAL(C_FLOAT), INTENT(IN ) :: X(6) !< Translational and rotational displacement (m, radians) relative to inertial frame. REAL(C_FLOAT), INTENT(IN ) :: XD(6) !< Translational and rotational velocity (m/s, radians/s) relative to inertial frame. REAL(C_FLOAT), INTENT(IN ) :: ZTime !< Current time in seconds REAL(C_FLOAT), INTENT( OUT) :: PtfmAM(6,6) !< Added mass matrix (kg, kg-m, kg-m^2) REAL(C_FLOAT), INTENT( OUT) :: PtfmFt(6) !< Platform forces -- [3 translation (N), 3 moments (N-m)] at reference point. END SUBROUTINE OrcaFlexUserPtfmLd #ifdef __GFORTRAN__ SUBROUTINE OrcaFlexUserPtfmLdFinalise() BIND(C) #else SUBROUTINE OrcaFlexUserPtfmLdFinalise() !!!BIND(C) #endif USE, INTRINSIC :: ISO_C_BINDING !DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE, ALIAS: 'OrcaFlexUserPtfmLdFinalise'::OrcaFlexUserPtfmLdFinalise !GCC$ ATTRIBUTES STDCALL :: OrcaFlexUserPtfmLdFinalise ! There is no data to pass. END SUBROUTINE OrcaFlexUserPtfmLdFinalise END INTERFACE ......... END MODULE OrcaFlexInterface
How can I fix it?
Thank you in advance.
Best regards,
Matteo Strada
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It is not possible to address your question without knowing the calling conventions used by the library that you are attempting to link with. It appears to me that incompatible attributes have been piled on (for example, DEFAULT and STDCALL) in an attempt to get the compiler to accept the code without error messages. That is rarely a good strategy, since the resulting code will not run or, worse, run and give incorrect results.
If you are able to call the library from gFortran using Fortran-C interoperability, you should be able to do the same from Intel Fortran. In other words, you should not require any #ifdef __GFORTRAN__ in your source code at all, and you should need no DEC$ directives in the code.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I tried compiling the code in #7, with the ALIAS attributes removed, with ifort 17.0 update one, and it worked for me.
MODULE OrcaFlexInterface ! USE NWTC_Library ! USE NWTC_LAPACK ! USE OrcaFlexInterface_Parameters ! USE OrcaFlexInterface_Types ! USE, INTRINSIC :: ISO_C_Binding IMPLICIT NONE PRIVATE ABSTRACT INTERFACE ! These are interfaces to the DLL #ifdef __GFORTRAN__ SUBROUTINE OrcaFlexUserPtfmLdInitialise(DT,TMax) BIND(C) #else SUBROUTINE OrcaFlexUserPtfmLdInitialise(DT,TMax) !!!BIND(C) #endif USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_FLOAT ! !DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE, ALIAS:'OrcaFlexUserPtfmLdInitialise'::OrcaFlexUserPtfmLdInitialise !DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE ::OrcaFlexUserPtfmLdInitialise !GCC$ ATTRIBUTES STDCALL :: OrcaFlexUserPtfmLdInitialise REAL(C_FLOAT), INTENT(IN ) :: DT REAL(C_FLOAT), INTENT(IN ) :: TMax END SUBROUTINE OrcaFlexUserPtfmLdInitialise #ifdef __GFORTRAN__ SUBROUTINE OrcaFlexUserPtfmLd( X, XD, ZTime, DirRoot, PtfmAM, PtfmFt) BIND(C) #else SUBROUTINE OrcaFlexUserPtfmLd( X, XD, ZTime, DirRoot, PtfmAM, PtfmFt) !!!BIND(C) #endif USE, INTRINSIC :: ISO_C_Binding, ONLY: C_FLOAT, C_CHAR ! !DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE, ALIAS:'OrcaFlexUserPtfmLd'::OrcaFlexUserPtfmLd !DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE ::OrcaFlexUserPtfmLd !GCC$ ATTRIBUTES STDCALL :: OrcaFlexUserPtfmLd CHARACTER(KIND=C_CHAR), INTENT(IN ) :: DirRoot REAL(C_FLOAT), INTENT(IN ) :: X(6) !< Translational and rotational displacement (m, radians) relative to inertial frame. REAL(C_FLOAT), INTENT(IN ) :: XD(6) !< Translational and rotational velocity (m/s, radians/s) relative to inertial frame. REAL(C_FLOAT), INTENT(IN ) :: ZTime !< Current time in seconds REAL(C_FLOAT), INTENT( OUT) :: PtfmAM(6,6) !< Added mass matrix (kg, kg-m, kg-m^2) REAL(C_FLOAT), INTENT( OUT) :: PtfmFt(6) !< Platform forces -- [3 translation (N), 3 moments (N-m)] at reference point. END SUBROUTINE OrcaFlexUserPtfmLd #ifdef __GFORTRAN__ SUBROUTINE OrcaFlexUserPtfmLdFinalise() BIND(C) #else SUBROUTINE OrcaFlexUserPtfmLdFinalise() !!!BIND(C) #endif USE, INTRINSIC :: ISO_C_BINDING ! !DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE, ALIAS: 'OrcaFlexUserPtfmLdFinalise'::OrcaFlexUserPtfmLdFinalise !DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE ::OrcaFlexUserPtfmLdFinalise !GCC$ ATTRIBUTES STDCALL :: OrcaFlexUserPtfmLdFinalise ! There is no data to pass. END SUBROUTINE OrcaFlexUserPtfmLdFinalise END INTERFACE END MODULE OrcaFlexInterface
>ifort /c /fpp /warn:all "2017-01-12 alias.f90" Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on IA-32, Version 17.0.1.143 Build 20161005 Copyright (C) 1985-2016 Intel Corporation. All rights reserved.
I don't think the decorate attribute is likely to be relevant for abstract interfaces anyway - you can probably delete it. DEFAULT is only relevant if you are using wacky command line options or similar, in which case, stop using wacky command line options and then you can delete it too.
Note with the code as presented, I think there are going to be significant differences between the calling conventions used by gfortran and ifort.
- For ifort and gfortran, if BIND(C) is specified, regardless of STDCALL, then scalar arguments are passed by reference unless explicitly specified otherwise. This is what your code does for gfortran.
- For ifort, if STDCALL is specified without BIND(C), then scalar arguments are passed by value unless explicitly specified otherwise. This is what your code does for ifort.
- For gfortran, if STDCALL is specified without BIND(C), then scalar arguments are passed by reference unless explicitly specified otherwise.
Note that ifort as of some recent version (2016??) supports the use of BIND(C) and attributes STDCALL together, and (as far as I can tell, I'm not so familiar with gfortran) behaviour is consistent with gfortran when things are specified that way.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear All
Thank you for your quick and accurate replies.
Now I have compiled the code that IanH posted and it worked. The problem was that I removed in a bad way the attribute ALIAS.
IanH I would like to thank you for your patience in explaining me all of this, I really appreciate.
Best Regards,
Matteo Strada
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You can modify the source code of your module and compile without error the modified code, but that is of little significance. What really matters is that the compiled code should conform with what the vendor library expects regarding the ABI. In particular, does the vendor library expect scalar arguments to be passed by value or address? What about its expectations regarding name decoration?
Is there a reason to use an abstract interface instead of a straightforward (i.e., concrete) interface? The following code, for example, makes use of the abstract interface but, if myInit() is the only routine with that interface, a simple interface would suffice and also be easier to understand.
program drvr use OrcaFlexInterface, only : OrcaFlexUserPtfmLdInitialise USE, INTRINSIC :: ISO_C_Binding, ONLY: C_FLOAT real (c_float) :: dtm, tmx procedure (OrcaFlexUserPtfmLdInitialise) :: myInit dtm = 1.5; tmx=7.5 call myInit(dtm,tmx) write(*,*) dtm,tmx end program
If, furthermore, the initialisation routine is actually named "OrcaFlexUserPtfmLdInitialise", there is no need to use an abstract interface at all.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear mecej4,
Thank you for your reply.
I am sorry but I can't answer to your questions since I don't know how this part of the program works. I am working to another part of it. Furthermore this is an optional functionality of the program and I don't need it.
Nevertheless I need this module to be present in the source code since if I decided to eliminate this part, I would have been forced to modify a very large part of the whole program and this is not the case.
So I just need to be able to compile the code, even if this part could be wrong.
I am sorry if I didn't have specified this before but I thought it would have had little importance.
Please tell me if this could impact the behaviour of the program, even if I don't use this part.
Thank you again.
Best regards,
Matteo Strada
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
To me the "first, do no harm (primum non nocere)" principle comes to mind. Since your module code, as shown, contains only declarations, i.e., no CONTAINS followed by subprogram code, there is no module code to be executed at all, so the question of correct/incorrect code does not apply. On the other hand, the module has probably a justification for its existence: it is probably USEd in some part of the code that you use when you build, even if you are not concerned with what that code does. If you modify the module source, you may cause that code to misbehave, and you will be held culpable. In effect, you could be hiding a small bomblet in the code.
I hope that there is some "project manager" who can decide and document how to proceed. Even if that project manager is just you, some discussion and documentation is definitely recommended.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In that case, I would place "Stop 'subroutine xxx entered unexpectedly' " statements as the first executable statement in each of those contained subroutines.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear mecej4
The MODULE has a CONTAINS section just after the END INTERFACE line. I have omitted that section since it is very long: there are many subroutines that are used in the program ONLY IF I decide to use this functionality. Every call of one of these subroutines has to pass an "IF" control that checks if I decided to use it. For this reason I told you that I need this module to be in the code, otherwise I had to parse the whole source code excluding all those CALLs, and for the moment it is an hard work.
Best Regards,
Matteo Strada
EDIT:
Maybe I could be misunderstood. The main program calls these subroutines in this way:
IF (Module_Orca) THEN CALL Orca_Init( ....) END IF
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page