I'm struggling to successfully compile a piece of code as a dll. I have Visual Fortran Composer XE 2011. Below are the relevant lines of code. When written as a main program and compiled into an .exe (with the visual studio parameters set correctly), everything works great. Notice that as a dll, I've had to add !DEC$ controls (found by searching forums, and set visual studio parameters) for the ExchangeDLL to see and have access to the EQUILIX subroutine, and to be visible to external calling programs. The EQUILIX subroutine calls the MKL subroutine DGESV. Upon compiling I get LNK2019 error . . . . unresolved external symbol _dgesv@32. The !ML_EXTERNAL DGESV doesn't seem to work.
I'm sure that there is something quite trivial to get this to compile and link correctly. The goal is that ExchangeDLL with be fully contained so that I can call it from Excel. Can someone suggest a solution?
DIMENSION :: DATARRAY(50)
DIMENSION :: KEQ(8),CHARGE(8),EXCHANGER(8),CHEMX(8),KEQLOG(8),AW(8),SW(8),FB(8)
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL, ALIAS : "ExchangeDLL" :: ExchangeDLL
!DEC$ ATTRIBUTES REFERENCE :: DATARRAY
!DEC$ ATTRIBUTES STDCALL, REFERENCE, ALIAS : "EQUILIX" :: EQUILIX
!DEC$ ATTRIBUTES ALIGN : 16 :: KEQ
!DEC$ ATTRIBUTES ALIGN : 16 :: CHARGE
!DEC$ ATTRIBUTES ALIGN : 16 :: EXCHANGER
!DEC$ ATTRIBUTES ALIGN : 16 :: CHEMX
! in this space arelines of code . . . .
! more lines of code here . . .. .
END SUBROUTINE ExchangeDLL
IMPLICIT DOUBLE PRECISION(A-H,O-Z)
DIMENSION :: KEQ(8),CHARGE(8),EXCHANGER(8),CHEM(8)
DIMENSION :: RCHEM(8),REXCHANGER(8)
DIMENSION :: CHEMTOT(8),IDCHEM(8),K(8)
DIMENSION :: COEFFICIENT(16,16),RHS(16),IPIV(16)
DOUBLE PRECISION KEQ,K
!DEC$ ATTRIBUTES DLLEXPORT, STDCALL, ALIAS : "EQUILIX" :: EQUILIX
!DEC$ ATTRIBUTES REFERENCE :: KEQ,CHARGE,EXCHANGER,CHEM,CEC,IFUNCTION,IERR
! in here are lines of code . . . . .
! more lines of code in here . . . . .
END SUBROUTINE EQUILIX
You have compiled this with /iface:stdcall, I think. Don't do that. I don't know what "!ML_EXTERNAL DGESV " is supposed to do - that is just a comment to the compiler.
Retired !! Awesome. . . . I'm just 3 to 5 years away from retirement.
I deleted the !ML_EXTER. . . . from both versions of the code. It's legacy from over 10 years ago when I first used mkl to solve a different problem. It was necessary on whatever compiler I was using back then. I deleted it from both the .exe and .dll versions of this code and indeed it's just trash. thank you.
You're correct. . . . i was using /iface:stdcall . . . . either out of ignorance or because I saw a post to do that last fall when I was struggling with this problem. I changed it to default and now the dll compiles just fine. I've also cleaned up the !DEC$ associated with EQUILIX as well, as Excel doesn't need to call it . . . . . it just needs to call ExchangeDLL. It compiles great. thank you for that one as well !!
So, the Excel macro can now successfully call ExchangeDLL and progress through EQUILIX to the other subroutines. However, it results in a fatal crash and Excel closes. This is the same result as using a different approach that has dead ended as well. I've two more versions of this code in which I downloaded the LAPACK codes, and dressed them up with all the !DEC$ information (as I did for EQUILIX). The version that compiles as an .exe works perfectly, just like the version that uses the Intel source of mkl and compiled as an .exe . However, the version that compiles as a .dll results in a fatal crash and Excel closes. In that version I've isolated the problem to the recursive subroutine DGETRF2.
Do I have to do something else special for such a recursive subroutine?
I don't see DGETRF2 in the code you posted, so I don't know what it does. What is the error message for the 'crash"? I'll note that the default stack size on Windows is rather small, so it might be that your recursive routine overflowed the stack, especially if it uses large local arrays. Since I am flying blind here, I'll simply suggest that you set the Fortran property Optimization > Heap Arrays to 0 in the DLL project and see if that makes a difference. This will use heap allocation for temporaries instead of the stack. If it were an EXE you were building, you could resize the stack, but you can't do that for a DLL.
For flying blind you've done amazingly well. Since the crash happens out of Excel, there is no error message that is interpretable. I don't know what DGETRF2 does either. It's just one of the mkl routines that's supposed to work. I use it blindly.
However, I did what you suggested for Heap Arrays with no resolution (still crashed). But then I happened to notice that while I was using the dll out of the "Release" subdirectory created by visual studio, the setting was incorrectly set to Debug. When I put it to the proper setting of Release and recompiled. . . . Excel used the dll with SUCCESSS !!! So it seems I had made a mess of the settings.
Thank You for your support. I've been stumped and stalled on this project for 6 months.
I've run into a new problem with this effort. While the dll and Excel that calls it work perfectly on my personal laptop, when copied to my work laptop the Excel gives an error when trying to call the dll . The error is: Run-time error '53': File not found: . . . . . .
Yes, I've correctly changed the path to the lib in Excel. I've confirmed this by copying a fortran dll that I created in 2002 (two compilers ago) into the same directory as the ExchangeDLL and called it from the same "exchange" Excel. Of course, it couldn't find the entry to the subroutine because it wasn't in there. But this did verify that Excel could find the dll file and that some work-laptop related restrictions weren't the cause of the "file not found". Furthermore, the old Excel that calls the old dll works just fine on my work laptop. So, it seems there shouldn't be a restriction issue.
Next, I then downloaded the Intel Mixed Language example codes (which I located from one of your assists in late 2016) on to my personal laptop (where the compiler is located), used Visual Studio to load the Fcall project (my older version of Studio couldn't open the newer.sln file), switched it to Release, cleaned and built the Fcall dll, made the correct path edit in the associated Excel for it (xltest), and it ran perfectly on my personal laptop. (My thought was that the project settings located in the downloaded Fcall project might correct some setting I had overlooked.) Copied xltest.xls and Fcall.dll to my work laptop, corrected the path, and once again "file not found".
Personal laptop is a Toshiba with Windows 7 Home Premium SP1, with i3 cpu (64bit) and Excel 2007.
Work laptop is an HP with Windows 10 Enterprise, with i5-7300U cpu and Excel 2016.
While my fortran executables (.exe) created with Visual Studio on my personal laptop work flawlessly on my work laptop, I'm at a loss as to what the issue might be with doing so with a dll. Do you have any suggestions as to what this issue might be?
That error is also given when a dependent DLL is not found. First, make sure you are building your DLL as a Release configuration and not Debug. You will then also need to install the Intel Fortran and Microsoft Visual C++ redistributables on the laptop. What may be easier in this case is to change the DLL project property Fortran > Libraries > Use Run-Time Libraries to "Multithreaded (/MT)" and not "Multithread DLL". I suggest this only in cases where you are calling the DLL from an interpreted language such as Excel or VB - don't use it if you are calling from Fortran or C++.