Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28701 Discussions

VBA - Intel Fotran Compatibility

aelliott
Beginner
1,126 Views
I am using Fortran DLLs with Visual Basic for Applications inside MS Excel. I have been successful in getting code to work with VBA on 1 box by using the /iface:cvf switch to compile the DLL.
However, if I copy the DLL and Excel workbook to another computer where I do not have the Intel compiler loaded (but do have the Compaq compiler), it will not run - generates a "file not found" error even though the file is clearly there.If I rebuild the DLL there with the Compaq compiler it works fine.
Vice versa happens if I copy a working DLL compiled with Compaq FORTRAN from that computer to the one with the Intel compiler. That is, I get a "file not found" error from VBA.
I would really like to hear from anyone who is working with VB and Fortran. I am using version 8.1 of the Intel compiler, v6.6b of the Compaq compiler and Visual Basic for Applications inside MS Excel.
I would also like to find a complete description of just what the /iface:cvf switch does. It is not included in the tables in the Intel compiler documentation.
Thanks,
Andy Elliott
0 Kudos
13 Replies
Steven_L_Intel1
Employee
1,126 Views
The /iface:cvf switch has the following effects:

- Makes the default calling mechanism STDCALL rather than CREF, with arguments passed by reference and routine names upcased
- Causes string argument lengths to be passed immediately after the address of the string rather than at the end of the argument list

I suspect that the problem you're having is that when you build the Intel Fortran DLL, it is linked against run-time DLLs that you are not copying to the other system. You'd have the same problem if you went the other way.

Get the free tool Dependency Walker and run it on your DLL. Find the Intel Fortran DLLs it is using (probably libifcorert.dll, maybe more) and copy those to a directory on the target system that is in the PATH environment variable (or copy them to the Windows System folder).
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,126 Views
Sounds simply like missing run-time dll libraries, which are different/differently named for two compilers. (dforrt.dll and libifcore.dll).

/iface:cvf, is, as far as I know, just a shortcut for /iface:stdcall + /iface:mixed_strlen_arg. Here's one explanation. It shouldn't be related with your problem though.

You can overcome the problem either by redistributing the RTL dll, or by statically linking your dll to the RTL -- change the setting for "run-time library" in both "C++" and "Fortran" categories to "Multi-threaded" or "Single-threaded" (instead of default "Single-threaded dll").
0 Kudos
aelliott
Beginner
1,126 Views

Thanks to you both. You are both right. By adding the Intel DLLs to the path on the non-Intel box, it works, and vice versa. And doing a static link for the DLL also works.

It is not clear (at least to me!) in the documentation that using the simple /dll switch changes the default link behavior to imply /libs:dll. If you want to get a DLL with static libraries, you have to specify both /dll and /libs:static. Using this approach, I was able to produce a DLL from either box that will run on the other. Ofcourse, the size of the DLL jumps from about 4K to about 325K, but they do work.

Thanks again,

Andy Elliott

0 Kudos
tenuti
Beginner
1,126 Views
I just run in this issue with my DLLs. I noticed that my pool of DLLs depends on:
libifcoremd.dll
libmmd.dll
msvcrt70.dll (indirect dependency)
Is there a different way to install those needed files in the windows/system32 folder or patching the PATH system variable? Both these methods require to patch part of the OS installation, but another option would be desiderable.
I noticed that it's enough putting the independent DLLs in the executable file folder, so this could be the desiderable solution for me.

Message Edited by tenuti on 04-20-200604:12 AM

0 Kudos
Steven_L_Intel1
Employee
1,126 Views
These DLLs need to be in a folder on PATH or, and this is the better solution if you are distributing an EXE, in the same folder as the EXE. Microsoft prefers this approach.
0 Kudos
aelliott
Beginner
1,126 Views

This difficulty should not occur, I think, if you have used the static link approach (/libs:static switch). However, if you are using VBA (not a stand-alone exec), you need to have code in the VBA to recognize the DLLs in the local directory. I use these two lines in my VBA subs that access code in the DLL:

ChDrive ThisWorkbook.Path
ChDir ThisWorkbook.Path

Andy Elliott

0 Kudos
plf
Beginner
1,126 Views

There's a problem to Elliotts approach:

If the VBA code is contained in a Excel template the workbook will typically not be saved and chdrive fails. This can be solved by "on error resume next"or similar. When the workbook is not saved "File not found" is returned when user calls the DLL.

Any suggestions how to solve the problem? Ofcause to tell the user to save the workbook before proceeding but.. crappy solution.

Maybe to get the original templates directory, but how?

0 Kudos
plf
Beginner
1,126 Views

There's a problem to Elliotts approach:

If the VBA code is contained in a Excel template the workbook will typically not be saved and chdrive fails. This can be solved by "on error resume next" or similar. When the workbook is not saved "File not found" is returned when user calls the DLL.

Any suggestions how to solve the problem? Ofcause to tell the user to save the workbook before proceeding but.. crappy solution.

Maybe to get the original templates directory, but how?

0 Kudos
DavidWhite
Valued Contributor II
1,126 Views
When calling a Fortran DLL from Excel VBA, what are the correct calling conventions?
My Fortran entry point is declared as

subroutine VERCHECK(NAME, VERSION)

!DEC$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE :: VERCHECK

!DEC$ ATTRIBUTES ALIAS: 'vercheck' :: vercheck

CHARACTER(LEN=*), INTENT(IN) :: NAME, VERSION

And in VBA, I have

Declare Sub Vercheck Lib "VerCheck.dll" _
Alias "vercheck" (ByVal Name As String, ByVal LName As _
Long, ByVal Version As String, ByVal LVersion As Long)

Call Vercheck(Name, Len(Name), Version, Len(Version))
The DLL can be called properly from another Fortran program, but I get Error 28, stack overflow from VBA.

0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,126 Views
In Intel Fortran, (unless you build with /iface:cvf), character lengths are passed at the end of argument list, rather than immediately following string argument. So, either add MIXED_STR_LEN_ARG to attributes (to force CVF behavior), or change the order of 2nd and 3rd argument in VBA.
0 Kudos
DavidWhite
Valued Contributor II
1,126 Views
Jugoslav,
Thanks for this solution. I changed the order in the VBA code as I cannot change back to the cvf option due to compatibility with other libraries.
Thanks,
David
0 Kudos
aelliott
Beginner
1,126 Views
How about putting VBA code to force save the file in the local directory in the Workbook_Open() sub in the template? Not pretty, but better than asking the user.
0 Kudos
plf
Beginner
1,126 Views
The "easy" solution is to wrap the program in an installer, andthrow the DLL in the PATH somewhere (fx. the windows system). Then the unsaved file is able to find the DLL.
Still I don't think it is a nice solution to force saving of the document, this seems strange to the user..

Message Edited by PLF on 05-26-200601:28 PM

0 Kudos
Reply