Declare Sub FortranCall Lib "C:\temp\Fcall.dll" (r1 As Long, ByVal num As String)
When ran it reports an error: runtime error 53, file not found c:\temp\fcall.dll
Anyone has any clue what could be wrong ?
I had the same problem - super frustrating!
I had the similar kind of declaration in Excel VBA:
Declare Sub FortranCall Lib "C:\temp\Fcall.dll" (r1 As Long, ByVal num As String)
It worked on my computer but it did not work on my boss's computer. All the spelling of the file name and the path specification were fine. My DLL was compiled in Microsoft Visual C++ 6.0. The problem was - A common cause for "File not found/Runtime error 53" is that the calling application cannot find dll's on which the dll in question actually depends!!! I gave my boss the DLL that I compiled in DEBUG mode - in this case DLL uses lots of other debug versions of DLL which not commonly found on regular computers. When I gave my boss RELEASE version of DLL it worked fine!
See also:
http://software.intel.com/en-us/forums/showthread.php?t=42472
I know this is a very old question, but I came across this issue the other day and thought I'd put an answer up for posterity. My VBA code calling a Fortran DLL worked fine on my computer, but not on my boss's or anyone else's computer. The problem ended up being dependency on other DLLs, despite compiling in "release" mode instead of "debug". I used Dependency Walker to check the dependencies in the DLL on a computer where it wouldn't work, found two DLLs which come with the intel compiler that were needed, and distributed these with my own compiled DLL.
–
–
–
Not sure what could be wrong.
I couldn't get my hands on an ifort compiler, but I tried your code by copying a random DLL to the Temp folder specified the Declare statement. When I run it, the error I get is: "Can't find DLL entry point FortranCall in C:\Temp\RandomDLL.DLL", which is consistent with using the wrong DLL (that is, the DLL was found, but it doesn't jive with the calling code).
You could try to replace the DLL you compiled with a random other DLL and see if you get the same error. If you do, it is a problem with the OS environment, not the compiler.
This is probably not very helpful, but may eliminate one or two possibilities.
Environment I used:
Win Vista,
Excel 2003
Well this may be way too late, but a number of issues to consider
1) The "calling convention" must match correctly. This has several different aspects, some of which are:
a) The capitalisation or not or mix of s/r and Arg names.
b) Srting calling conventions. In your code you have used some "mix" of things, and seem to be missing some bits.
For example, try this
subroutine FORTRANCALL (R1, NUM) ! notice capitalisation
!DEC$ ATTRIBUTES DLLEXPORT :: FORTRANCALL ! notice capitalisation and default "calling convention" (this varies between compilers)
! but older CVF and Intel compilers default to CDECL, which you can set in your "properties" etc.
! Its been a while but I think newer IVF have changed to a different default convention
! e.g. if you were doing this, say, in GCC/gFortran, there would be a much longer discussion
integer, intent(in) :: r1
Character(Len=10), intent(out) :: num ! you might be able to use Character(Len=*) so long as its fixed on the VBA side
! remove this => !DEC$ ATTRIBUTES REFERENCE :: num
num = ''
write (num,'(i0)') r1 * 2
return
end subroutine FortranCall
On the VBA-side, the declaration is:
Declare Sub FortranCall_XX Lib "C:\ ... your path ...\Fcall.dll.dll" _
Alias "FORTRANCALL" (R1 as Long, ByVal NUM As String, ByVal NumLen as Long)
NOTICE the extra Arg for the String len, this only appears on the VBA side, and ONLY when String is passed ByVal (any other string passing and especially arrays of strings is a giant issue ... doable, but be prepared for some homework).
Also, the string len here simply follows the string in terms of Arg position. However, if num was located earlier on, the the location of NumLen would be either just following the Arg num, or at the end of Arg list, depending on the calling convention.
Also, when you create a DLL, the compiler often also creates a "Def" file. You don't need to access the Def file directly when using VBA/Fortran. However, looking inside it will show you the exact "naming style" of what the compiler thinks your s/r should be called. For example, with some calling conventions, the Def file might show the name of your s/r as something like
__fortrancall@12
... whatever the Def files says, is what you must use in the VBA declaration Alias "__fortrancall@12"
... these things require a lengthy discussion for general implementation with different calling conventions/compilers.
BTW: I added the "_XX" purely to allow the actual VBA UDF to have the "obvious name", say FortranCall, or whatever ... a reasonable habit if you will be doing a lot of this, and especially with Functions etc., but not too important here.
and the VBA sub becomes:
Private Sub CommandButton1_Click()
Dim r1 As Long
Dim num As String * 10
Dim numlen as Long
numlen = 10 ' required string len, can automate via intrinsics etc
r1 = 123
Call FortranCall_XX(r1, num, numlen) ' notice the extra Arg
TextBox1.Text = "Answer is " & num ' you may wish to add Trim() or something in case returned num does not require 10 chars
End Sub
2) Do you really need to pass num as a string? Passing strings between VBA and DLL's is a big can of worms. Why not pass num as a Double or something?
If it must be a string and if it's ByVal, then you must also include the string length as ByVal Long on the VBA-side (since in Fortran the string len is a hidden value) as shown above.
You can pass by Ref and with/without the extra StringLen if you know how use (Cray) Pointers or Variants on the Fortran side to convert the VBString to a Fortran string etc. ... a long long discussion.
3) A more general and "certain" way to distribute/connect to a dll is to convert the XL sheet/module to an XLA ... i.e. an Add-In. Then the XLA and DLL are (usually) put into the same Dir, and the Addin is Added to Excel via Tools/Addins etc ... which has browse to ensure the correct path.
Then, you can also call your s/r's from any workbook/sheet etc., not just the one workbook.
I had the same recently with ifort 14, and the problem disappears when I compile with
ifort /dll /libs:static /threads
Instead of just
ifort /dll
The message "file not found" often arise when the DLL has a dependency on another DLL which is not on system path (I had this with gfortran, and a DLL in MinGW32\bin, for instance). But I didn't find such a dependency here, rather strange.
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.