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

Cannot access fortran dll routines from VB macro

cathleenmcguiness
632 Views
Hi,

So I've been googling for the better part of a day but can't seem to find a fix to this one.

I have a super simple fortran routine which I created simply for testing:

SUBROUTINE test(feature)

!DEC$ ATTRIBUTES DLLEXPORT :: test

IMPLICIT NONE

INTEGER, INTENT(IN) :: feature

PRINT*, feature

END SUBROUTINE test

which I compile with

/heap-arrays /fpstrict /static /threads -link /SUBSYSTEM:CONSOLE /IMPLIB:"./test.lib" /MACHINE:I386 /DLL

It compiles without problems and can be accessed from a fortran main, also without problems. However, if I try calling test from an Excel macro, Excel claims that the library in question (test.lib) cannot be found despite the file (and all intermediate files created by the fortran compiler) being in the same directory as the Excel sheet from which I'm trying to run the macro.

The macro looks like this:

Declare Sub test Lib "C:\\Users\\cathleen\\Projects\\Excel_Fortran\\test.lib" (feature As Integer)

Sub blah()

feature = 2
Call test(feature)

End Sub

I tried switching to test.dll instead which gives another number for the runtime error (53 vs. 48) but the same message.

Obviously, the error message doesn't tell the whole story, I guess it's some sort of compiler library or similar that for some reason isn't available via Excel? If anyone can shed any light on this it would be much appreciated, I'm getting absolutely nowhere on this and the microsoft help forums' only suggestion is to spell check.

I'm using IVF 12.0.5.221 for Windows and MS Office 2010.

Thanks,
Cathleen

0 Kudos
9 Replies
Steven_L_Intel1
Employee
632 Views
Rather than /static use /libs:static . /static means something else.

The general advice here is to run Dependency Walker on your DLL and see what it complains about.
0 Kudos
IanH
Honored Contributor II
632 Views
If you are accessing this routine from within 32 bit Excel (I have zip experience with 64 bit office), then it needs to be declared with the stdcall calling convention. Also, when your fortran program is called by Excel there is no console, so PRINT is going to cause you substantial grief. In the example below I use WRITE to an unopened unit - the output will go to a file named fort.100 or similar for debugging as per the Intel docs. I've also used the alias attribute to avoid doubt about the external name of the routine.
[fortran]SUBROUTINE test(feature) !DEC$ ATTRIBUTES DLLEXPORT :: test !DEC$ ATTRIBUTES STDCALL :: test !DEC$ ATTRIBUTES ALIAS('test') :: test IMPLICIT NONE INTEGER, INTENT(IN) :: feature WRITE (100,*) feature END SUBROUTINE test [/fortran] Your VBA declaration needs to reference the DLL, not the lib. Note that an integer in 32 bit VBA is only two bytes long (INTEGER(2) in fortran). To interface with the default four byte integer use a long. Note that compiler options can change the size of the default integer in Fortran - consequently it is a good idea to explicitly designate the kind on the Fortran side using a parameter. The stdcall attribute in Fortran changes the default calling convention to be by value - I can never remember how VBA works, so again for the avoidance of doubt and in-source documentation it is best to specify that the argument is being passed by value.

[vb]Declare Sub test Lib "C:UserscathleenProjectsExcel_Fortrantest.dll" (ByVal feature As Long) Sub blah() Dim feature as long feature = 2 Call test(feature) End Sub[/vb]To avoid issues with DLL dependencies (what Steve is referring to) I suggest you install the latest compiler runtime DLL's using the Intel provided msi.

0 Kudos
cathleenmcguiness
632 Views
Thanks for the replies but I'm afraid they don't make the issue go away;

- Changing from static to libs:static does nothing as far as I can see and dependency walker says everything is fine.

- Swapping from a regular integer to a long causes Excel to crash.

I've also tried doing this with IVF 11.1.067 and 12.1.3.300 without progress.
0 Kudos
IanH
Honored Contributor II
632 Views
Are you using 32 bit office? Did you add the stdcall attribute? How does Excel crash?

If Excel crashes that implies to me that your DLL is being found and loaded by Excel so the nature of the issue has changed from your original post.

Have you tried setting a breakpoint on the first executable line of your subroutine and debugging the Excel call? (Are you compiling the DLL in a debug configuration?)

Show your current Fortran and VBA code again.
0 Kudos
MWind2
New Contributor III
632 Views
I tried to duplicate with my old Fortran 10.0.025, Office 2010 Excel 32-bit and VS05, Win64HPremium. I tried ByRef and not both with stdcall, no problems. I did crash Excel by stepping in the VS05 debugger rather quickly or before everything was initialized with the claim that file "write, 100" was still open. I would create an error in Excel vba debugger that would respond to reset when I did not link with libs/libs:static and the rest of the command line was /threads /dbglibs because an emt64 lib was being used according toDepends 2.2.6; with libs:static everything was 32 bit. No console, used dllwith sample, MT debug.
0 Kudos
IanH
Honored Contributor II
632 Views
Grrr. In #2 I have a syntax error:

!DEC$ATTRIBUTESALIAS('test')::test

should be:

!DEC$ATTRIBUTESALIAS:'test' ::test

Apart from that I can get my fortran snippet and VBA snippet to talk happily to each other. Note that the fort.100 file will probably end up in your "My Documents" directory.

If you are using 32 bit excel, and the fortran procedure is not declared as stdcall then you will (eventually) get stack corruption. Without the stdcall attribute the "default" calling convention in ifort is by reference, so things may seem to be working, but if you experiment (perhaps try a call that has multiple arguments and try to do something non-trivial in the VBA procedure after the call) you'll soon see trouble. 32bit VBA expects the called procedure to clean up its stack, without the stdcall attribute the fortran procedure will not do that.


0 Kudos
MWind2
New Contributor III
632 Views
How would you get your module to link with c++ as written? I have not been able to get something similar linked to a c++ program using extern "C" __declspec(dllimport) void__stdcall test.... The export is "test" but c++ seems to be looking for __imp__test@....
0 Kudos
IanH
Honored Contributor II
632 Views
I would normally just provide a separate C interface.

VBA looks for the undecorated name while C++ is looking for the decorated name. If you add

!DEC$ ATTRIBUTES DECORATE :: test

to the fortran file you'll get both style of names exported.


0 Kudos
MWind2
New Contributor III
632 Views
Thanks, again. I can see now why a separate interface would be better.
0 Kudos
Reply