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

Problem calling Fortran dll from VB2005

5applerush
Beginner
891 Views
An associate of mine has recompiled his Fortran app into a dll and asked me to try to call it. I am attempting to write a gui for it in Vb2005. He has exposed an init routine with no arguments. When I call it Vb returns an "Access violation exception". Skip this next part at will - here's a blurb from MSDN about it:
--------------------------
"An access violation occurs in unmanaged or unsafe code when the code attempts to read or write to memory that has not been allocated, or to which it does not have access. This usually occurs because a pointer has a bad value. Not all reads or writes through bad pointers lead to access violations, so an access violation usually indicates that several reads or writes have occurred through bad pointers, and that memory might be corrupted. Thus, access violations almost always indicate serious programming errors. In the .NET Framework version 2.0, an AccessViolationException clearly identifies these serious errors."
---------------------

I believe that his app normally goes out and grabs a bunch of memory which it then manages during execution. Is it reasonable to suspect that this is causing my (now Parent) .Net app to freak out and throw this error?

Any help GREATLY appreciated!

Danny
0 Kudos
5 Replies
Steven_L_Intel1
Employee
891 Views
You can read an article I wrote on access violations, but just as an overview for your case. Do you know if the error occurs while the routine is still executing or might it happen on return? If the latter, make sure that the Fortran routine specifies the STDCALL calling mechanism (which may also require specifying an ALIAS to make the name into something VB likes).

You can debug a Fortran DLL called from VB.NET. Both projects should be in the same "solution" and you have to change the Debug property of the VB project to allow debugging of unmanaged code. Then you should be able to get a break in the debugger when the error occurs.

Simply doing dynamic memory allocation itself is not a problem, as long as the memory is handled properly.
0 Kudos
5applerush
Beginner
891 Views
Hi Steve, Thanks for such a quick response. I read your article with great interest. Unfortunately, I don't know whether the error occurs during, or upon return of the routine in the Fortran dll. As far as my visual basic code goes - currently, it's just a one-liner (simplicity is best at first!). I was unaware that I could debug a fortran dll inline with my VB app. I could have my associate bring me a copy of his source. Would this require the installation of his fortran compiler on my machine then? I ask this because my understanding, was that there is no way to debug a "windows" (non-COM, non-.Net) dll in VB.... or is this leftover knowledge from vb6? Thanks, Danny
0 Kudos
anthonyrichards
New Contributor III
891 Views

Are you CALLing a FUNCTION by mistake?
Anyway, if your Visual Basic is very similar to the Visual Basic used in Microsoft EXCEL, here is some Fortran code used to build a DLL that is called from Visual Basic embedded in an EXCEL worksheet (the Visual Basic code is shown below). Just compile and build the DLL (called DLL_TEST.DLL here) and copy it to the C:windowssystem32 folder so that a default search for it would find it. Attached In the attached Zipped archive is an Excel file that contains and makes use of the Visual Basic calls. You will probably have to modify macro security in EXCEL to get it to run. P.S. I use Compaq Visual Fortran, but the Fortran is nothing special. The main thing is to get the calling convention right and make sure the Function/routine names exported from the DLL agree with what the Visual Basic code will use for them (i.e. pay attention to case-sensitivity! This is what the ALIAS attributes in the compiler directives do).

On the principle of learning to walk before you try running, I coded the simplest code I could think of to add and/or multiply the contents of two EXCEL cells and get the correct answer returned.

I have been able to get correct values returned to an EXCEL
cell using the formula reference =DoMult(b2,c2) for example
{to multiply the contents of the two indicated cells, b2 and c2},
so long as I include the REFERENCE attribute in the compiler
directive included in the FORTRAN code for function DOMULT.
If I omit REFERENCE and use STDCALL alone, the number returned
is wrong.
If I include both attributes, as shown below, I get the correct value
returned to EXCEL.

Here is the FORTRAN code used to create the dynamic-link
library DLL2_TEST.DLL, which was copied to the /SYSTEM/ folder,
which is in most search paths, so that it will be found automatically
FUNCTION COMPUTEMULT ( ARG1, ARG2 )
!DEC$ ATTRIBUTES DLLEXPORT,STDCALL,REFERENCE,ALIAS:'ComputeMult' :: COMPUTEMULT
REAL*4 ARG1, ARG2, COMPUTEMULT

COMPUTEMULT = ARG1 * ARG2

END FUNCTION COMPUTEMULT

FUNCTION COMPUTEADD( ARG1, ARG2 )
!DEC$ ATTRIBUTES DLLEXPORT,STDCALL,REFERENCE,ALIAS:'ComputeAdd' :: COMPUTEADD
REAL*4 ARG1, ARG2, COMPUTEADD

COMPUTEADD = ARG1 + ARG2

END FUNCTION COMPUTEADD

SUBROUTINE COMPUTEBOTH ( ARG1, ARG2, ARG3 )
!DEC$ ATTRIBUTES DLLEXPORT,STDCALL,REFERENCE,ALIAS:'ComputeBoth' :: COMPUTEBOTH
REAL*4 ARG1, ARG2, ARG3(2)

ARG3(1) = ARG1 * ARG2
ARG3(2) = ARG1 + ARG2

END SUBROUTINE COMPUTEBOTH

Here is the VisualBasic code used in the EXCEL worksheet
(I have spread the longer PUBLIC statements over two lines for ease of
visibility in this restricted space)
essentially, I use 'wrappers' such as DoAdd( arg1, arg2) etc. for the calls to
the FORTRAN functions , such as ComputeAdd(X,Y). The message boxes were just for show.

**NOTE: If you want to use REAL*8 (i.e. double precision) in
the FORTRAN, just define the VisBasic functions and their
arguments as Double rather than Single.

Public Declare Function ComputeMult Lib "C:Winntsystem32dll2_test.dll"
(A1 As Single, A2 As Single) As Single
Public Declare Function ComputeAdd Lib "C:Winntsystem32dll2_test.dll"
(A1 As Single, A2 As Single) As Single
Public Declare Sub ComputeBoth Lib "C:Winntsystem32dll2_test.dll"
(A1 As Single, A2 As Single, A3 As Single)
Public Function DoMult(X As Single, Y As Single) As Single
MsgBox "X= " & X
MsgBox "Y= " & Y
Z = ComputeMult(X, Y)
MsgBox "X*Y= " & Z
DoMult = Z
End Function

Public Function DoAdd(X As Single, Y As Single) As Single
MsgBox "X= " & X
MsgBox "Y= " & Y
Z = ComputeAdd(X, Y)
MsgBox "X+Y= " & Z
DoAdd = Z
End Function

Public Function DoBoth(X As Single, Y As Single,
ISWITCH As Integer) As Single
Static Z(1 To 2) As Single
MsgBox "X= " & X
MsgBox "Y= " & Y
MsgBox "Iswitch= " & ISWITCH
Rem Iswitch=0 calls routine to get both
Rem values and returns the first
If ISWITCH = 0 Then
Call ComputeBoth(X, Y, Z(1))
MsgBox "First value = Product = " & Z(1)
DoBoth = Z(1)
Else
Rem Iswitch not =0 calls routine to get both
Rem values and returns the second
Call ComputeBoth(X, Y, Z(1))
MsgBox "2nd value = Sum = " & Z(2)
DoBoth = Z(2)
End If
End Function

0 Kudos
5applerush
Beginner
891 Views
Hi Anthony,
Sorry for the late response. To answer your question, we checked to ensure that my call was formatted properly (sub / function). We went back to small routines as you suggested, and got them working. After a week of wrangling, we are now able to get my associate's app running via a call from my front-end. Unfortunately, there are subtle problems still. His app is actually mixed language fortran90 / C. Once his code is compiled as a dll, he is able to invoke it via a call from another fortran (test) app. However, when we invoke the same dll from VB2005 or VB6, the app starts but appears to ignore the portions of initialization written in C. I realize this is far too general of a description of the problem for you guys to lend help - I guess I'm just fishing in case my situation rings a bell with someone who's had a similar experience. For now, my associate says he will attempt to write a Com in Fortran for us to communicate through.

I welcome any additional comments or advice.

Thanks for your help!
Danny
0 Kudos
anthonyrichards
New Contributor III
891 Views

Which of the following is correct:
The entry to your colleague's DLL is via a C-routine, or
The entry to your colleague's DLL is via a Fortran-routine?

When you call this routine from a pure Fortran application, every thing is hunky-dory.
When you call this routine from a VB6,some thing odd happens (some initialisation fails? whatever that means).

When you call this routine 'from your front end', the DLL app runs (but you fail to say what your front end is) and you do not say if the app runs as expected.

It looks to me like you could still be having C or VB6-calling-Fortran mismatching. Could unexpected argumentmix-up explain the 'lack of initialisation' in the C part of the DLL?

0 Kudos
Reply