- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
My problem is that I've been unable to call a function in a CVF (v. 6.6) compiled program with IVF (2020 Update 4), running on Windows 10, without an error.
I've spent several long days searching, reading, and trying everything I could think of, but I can't solve this programming problem. I need help!
Although I've been using Fortran for a long time, I've gotten along without really understanding most of what's going on under the hood. So please excuse my ignorance -- and the klutzy but hopefully functional programming.
The CVF function returns some numerical values in variables. When I run the calling IVF program in debug mode, I can see that all the returned values are correct. However, when exiting the IVF subroutine I get the error message
Run-Time Check Failure #2 - Stack around the variable '##' was corrupted.
where '##' is '.T3' when calling Example1 below that returns an array and '_EXP1$DCPXOUT5' when calling Example2 that returns individual values.
All the reading points to a problem with the different calling conventions of CVF and IVF. From their documentation it appears that that CVF adds the number of arguments but IVF doesn't, and IVF cleans up the stack and allows a variable number of arguments which CVF doesn't. If that's the problem, what I need to know is what ATTRIBUTES I need to put into the CVF procedures, or if I can just use !DEC$ ATTRIBUTES DLLEXPORT :: <subroutine name> in CVF and somehow fix the problem in the calling IVF subroutine. You can see I've added ALIAS attributes but that makes no difference, and other attributes I've tried don't solve the problem either. It's not clear what the INTERFACE blocks are supposed to do, and they make no difference one way or the other with regard to the problem. Or if I need to do something else, what?
To answer a question I'm sure I'll be asked -- why use CVF at all if I can modify the source files and compile it -- it's because CVF came with the IMSL math package. IVF (at least the "composer" version I have -- doesn't, and I want to use some of the IMSL functions. (IMSL now costs a lot of $$, especially for the hobby use I'm putting it to.) The plan is to make a CVF DLL that calls some functions and outputs them so they'll be available to IVF programs. The CVF compiler I had before migrating to Intel many years ago still runs on the old XP machine where it was originally installed -- it won't even try to install on my Windows 10-64 bit machine.
So can anyone please tell me what I need to do to get this to work? I'll appreciate it very much!
Of course I'm using the CVF DLL .lib file as a reference when building the IVF program, and both the CVF DLL and IVF program build without any errors or warnings.
Here are simplified versions of a couple of the CVF functions:
SUBROUTINE Example1(dcpx1, intDim, intOut, dcpxArray)
IMPLICIT NONE
!DEC$ ATTRIBUTES DLLEXPORT :: Example1
!DEC$ ATTRIBUTES ALIAS : "Example1" :: Example1
COMPLEX (KIND =
INTEGER (KIND = 4) :: intDim
INTEGER (KIND = 4) :: intOut
COMPLEX (KIND =
INTEGER (KIND = 4) :: intI
REAL (KIND =
intOut = 5
dcpxArray(1) = dcpx1
DO intI = 2, intDim
dcpxArray(intI) = cmplx(intI, -1.1D0 * intI,
END DO
END SUBROUTINE Example1
SUBROUTINE Example2(dcpx1, intDim, intOut, dcpxOut1, &
dcpxOut2, dcpxOut3, dcpxOut4, dcpxOut5)
IMPLICIT NONE
!DEC$ ATTRIBUTES DLLEXPORT :: Example2
!DEC$ ATTRIBUTES ALIAS : "Example2" :: Example2
COMPLEX (KIND =
INTEGER (KIND = 4) :: intDim
INTEGER (KIND = 4) :: intOut
COMPLEX (KIND =
COMPLEX (KIND =
COMPLEX (KIND =
COMPLEX (KIND =
COMPLEX (KIND =
INTEGER (KIND = 4) :: intI
COMPLEX (KIND =
INTEGER (KIND = 4) :: intMaxMinDim
COMPLEX (KIND = 8), PARAMETER :: dcpxZERO = (0.D0, 0.D0)
intOut = 5
intMaxMinDim = MAX(MIN(intDim, 5), 1)
dcpxOut1 = dcpx1
dcpxOut2 = cmplx(2., -2.2,
dcpxOut3 = cmplx(3., -3.3,
dcpxOut4 = dcpxZERO
dcpxOut5 = dcpxZERO
END SUBROUTINE Example2
-------- and the IVF calling program (which intentionally produce any output) ----------
INTEGER (KIND = 4) function WinMain(hInstance, hPrevInstance, &
lpszCmdLine, nCmdShow )
IMPLICIT NONE
!DEC$ ATTRIBUTES STDCALL, DECORATE, ALIAS : 'WinMain' :: WinMain
INTEGER (KIND = 4) :: hInstance
INTEGER (KIND = 4) :: hPrevInstance
INTEGER (KIND = 4) :: lpszCmdLine
INTEGER (KIND = 4) :: nCmdShow
WinMain = 0
Call Exp1
END FUNCTION WinMain
SUBROUTINE Exp1()
IMPLICIT NONE
INTERFACE
SUBROUTINE Example1(dcpx1, intDim, intOut, dcpxArray)
IMPLICIT NONE
!DEC$ ATTRIBUTES DLLEXPORT :: Example1
!DEC$ ATTRIBUTES ALIAS : "Example1" :: Example1
COMPLEX (KIND =
INTEGER (KIND = 4) :: intDim
INTEGER (KIND = 4) :: intOut
COMPLEX (KIND =
END SUBROUTINE Example1
END INTERFACE
INTERFACE
SUBROUTINE Example2(dcpx1, intDim, intOut, dcpxOut1, &
dcpxOut2, dcpxOut3, dcpxOut4, dcpxOut5)
IMPLICIT NONE
!DEC$ ATTRIBUTES DLLEXPORT :: Example2
!DEC$ ATTRIBUTES ALIAS : "Example2" :: Example2
COMPLEX (KIND =
INTEGER (KIND = 4) :: intDim
INTEGER (KIND = 4) :: intOut
COMPLEX (KIND =
COMPLEX (KIND =
COMPLEX (KIND =
COMPLEX (KIND =
COMPLEX (KIND =
END SUBROUTINE Example2
END INTERFACE
!DEC$ ATTRIBUTES DLLIMPORT :: Example1
!DEC$ ATTRIBUTES DLLIMPORT :: Example2
INTEGER (KIND = 4), PARAMETER :: intDIM = 3
COMPLEX (KIND =
INTEGER (KIND = 4) :: intOut
COMPLEX (KIND =
COMPLEX (KIND =
COMPLEX (KIND =
COMPLEX (KIND =
COMPLEX (KIND =
COMPLEX (KIND =
INTEGER (KIND = 4) :: intI
INTEGER (KIND = 4) :: intMaxMinDim
dcpx1 = (2.D0, 3.D0)
CALL Example1(dcpx1, intDIM, intOut, dcpxArray)
CALL Example2(dcpx1, intDIM, intOut, dcpxOut1, &
dcpxOut2, dcpxOut3, dcpxOut4, dcpxOut5)
END SUBROUTINE Exp1
Thanks!
Roy
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The CVF compiler used a different calling convention by default: STDCALL. This interferes with the current default, CDECL. The difference has to do with the way the stack is managed and a mismatch can therefore lead to all manner of interesting behaviour, most of which is completely unwanted.
In the properties window (External Procedures/Calling Convention) I see a number of options, one of them being /ifacecvf. My guess is that you will need this setting.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Roy,
If you check any of the lines in your in-line Fortran code above that start with COMPLEX, you will see that some character sequences have been converted by the forum posting software to invisible smileys, so much of the code is "flyover territory". The next time when you wish to post, use the "code" button (first "..." button to expand the menu icons, then the </> icon, choose Fortran and paste in the code). Or, zip up the source files and attach the zip to your post, or upload the zip file to a cloud server such as Google Drive and post a link in your post.
Now, to answer your question and make suggestions for moving forward. Which IMSL routines do you use? If you list them, it may be possible to suggest replacement routines from MKL, MATH77, or other libraries.
If you must use the IMSL 4.0 that came with CVF from Ifort compiled code, your choices are limited and error-prone. It so happens that it is possible to have CVF 6.6C installed and functioning on Windows-10/11, but the procedure is messy and to be avoided unless you are comfortable with assembler level code. Because CVF was copyrighted code, it is not possible to share files legally.
The least troublesome approach for using the IMSL 4.0 that came with CVF from Ifort-32-bit, in my view, is to build a 32-bit DLL from the IMSL 4.0 library that came with CVF, and to link to the associated import/export library from 32-bit Intel Ifort, along with the option /iface:cvf . For example, to build an EXE from Ifort 2021.8.0, using the example source code on p.591 of the IMSL MATH.PDF manual:
S:\IMSL>ifort /iface:cvf xqdags.f c:\LANG\cvf\DF98\IMSL\LIB\imsldll.lib
Again, let us note that the issue is about how to use 20 year-old "legacy" software with a current compiler, so failure should not be unexpected.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@mecej4 so failure should not be unexpected.
I had to laugh, my 15 year old daughter, who is sick and home from school, asked me a question at the weekend. When I answered she stopped me and said, be direct Dad. I read this sentence and thought kindly of a child who is miserable and thought "Expect failure".
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@mecej4 wrote:
Roy,
If you check any of the lines in your in-line Fortran code above that start with COMPLEX, you will see that some character sequences have been converted by the forum posting software to invisible smileys, so much of the code is "flyover territory". The next time when you wish to post, use the "code" button (first "..." button to expand the menu icons, then the </> icon, choose Fortran and paste in the code). Or, zip up the source files and attach the zip to your post, or upload the zip file to a cloud server such as Google Drive and post a link in your post.
Now, to answer your question and make suggestions for moving forward. Which IMSL routines do you use? If you list them, it may be possible to suggest replacement routines from MKL, MATH77, or other libraries.
If you must use the IMSL 4.0 that came with CVF from Ifort compiled code, your choices are limited and error-prone. It so happens that it is possible to have CVF 6.6C installed and functioning on Windows-10/11, but the procedure is messy and to be avoided unless you are comfortable with assembler level code. Because CVF was copyrighted code, it is not possible to share files legally.
The least troublesome approach for using the IMSL 4.0 that came with CVF from Ifort-32-bit, in my view, is to build a 32-bit DLL from the IMSL 4.0 library that came with CVF, and to link to the associated import/export library from 32-bit Intel Ifort, along with the option /iface:cvf . For example, to build an EXE from Ifort 2021.8.0, using the example source code on p.591 of the IMSL MATH.PDF manual:
S:\IMSL>ifort /iface:cvf xqdags.f c:\LANG\cvf\DF98\IMSL\LIB\imsldll.lib
Again, let us note that the issue is about how to use 20 year-old "legacy" software with a current compiler, so failure should not be unexpected.
I am looking for the same, your explanation is very well, great way to define each step, helpful for everyone especially for me, thanks
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
To @JohnNichols: Expect failure, then -- unless you are willing and can afford to put Hercules on the job.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for all the help! Setting the External Procedures to CVF (/iface:cvf) in the IVF calling program solved the problem of getting the results from the CVF compiled DLL. But although the example that I posted and was used for testing was an IVF .exe program, the intended object was an IVF DLL that I could call from other IVF programs or DLLs. And setting the External Procedures to CVF also affected the convention used for exporting routines. And again my ignorance of what's going on under the hood forced me into a trial and error mode to make the functions in that DLL exportable to other IVF objects.
The solution was simple, though. In the /iface:cvf DLL I simply added DEFAULT to all the procedure export statements :
!DEC$ ATTRIBUTES DLLEXPORT, DEFAULT :: <procedure name>
So now I've got my IMSL functions usable and easily callable from a standard IVF program or DLL. The functions that I have immediate use for are Bessel and Kelvin functions with complex arguments, but I've come across standard and hyperbolic trig functions with complex arguments from time to time.
It's not uncommon for me to expect defeat, but I don't often accept it. And this was one of those cases where I was more determined to figure out how to get those IMSL functions than just to have them by some easier means.
Roy
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well done, it is fun to get it right and then to tell the world, or a small subset.
@mecej4 usually you are better at solving tough problems than Hercules.
By the way, I often wondered why HGC had such graphics market share early on and then died.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page