I'm having trouble with some Fortran I've compiled as a DLL. When I call it via VBA, it crashes Excel instantly. The original Fortran is quite large, and requires a licence to some of it, so I've thrown together a simple function. It also crashes, although the crash isn't instant now - it manages to cycle through the "Excel has stopped working" messages.
I think the original Fortran should work, because if I change the Function declaration to a Program, replace the function line with a command to write the value to an output file, and compile as .exe, it works. The same goes for my simple code.
On 11/06/15 11:22, Ben Firth wrote:
> My simple code is times2.for:
> FUNCTION TIMES2(VBANUM)
This is FORTRAN, right? So VBANUM is passed *by reference*, (or so it
was for *all* function and subroutine arguments, when I last wrote any
FORTRAN -- about 15 years ago), yet here...
> Public Declare Function times2 Lib "C:\F\doubling.dll" (ByVal VBANUM
> As Double) As Double
...you declare the interface in VBA, with VBANUM passed *by value*, so
at the very least, your TIMES2 function will get garbage for its VBANUM
Now, as to why this might crash Excel:
- The value passed will be interpreted as an address; that may or may
not be an address from which the process is allowed to read, when
TIMES2 attempts to access what it thinks is the value for VBANUM,
but if it isn't readable a memory violation (segmentation fault)
will occur; this crashes the process.
- Even if the false address does represent readable memory, if the[*]
processor is 32-bit that address occupies only four bytes of stack
space, but your VBA has pushed eight bytes, (the size of a double).
Believing that only four bytes are used to pass the VBANUM address,
when it comes to return, TIMES2 will pop only four bytes off the
stack, leaving the additional four bytes as a stack misalignment;
this will almost certainly result in garbage being loaded into the
instruction pointer, soon after TIMES2's return, and the process
heads off into the twilight zone, and ultimate oblivion.
[*]: even if *your* processor is 64-bit, the focus of this list is on
compilers which target 32-bit, so *the* processor in question is 32-bit.
MinGW-users mailing list
This list observes the Etiquette found at
We ask that you be polite and do the same. Disregard for the list etiquette may cause your account to be moderated.
This is FORTRAN, right? So VBANUM is passed *by reference*, (or so it was for *all* function and subroutine arguments, when I last wrote any FORTRAN -- about 15 years ago), yet here...
...you declare the interface in VBA, with VBANUM passed *by value*, so at the very least, your TIMES2 function will get garbage for its VBANUM argument.
Yes, this is Fortran. When I use ByRef (or don't specify) in VBA, it comes up with a "Bad DLL calling convention" error. I assumed this meant I had misunderstood something along the way, and so I changed it to ByVal, and it appeared to work (except, you know, the crashing part). Any idea what else I've done wrong?
Interestingly, I didn't have this issue with the original Fortran. The only thing I had set as ByVal was a string, which I understand is necessary. The rest were left as is, which I believe leaves them as ByRef. That one crashes too, but it doesn't give me any grief about calling conventions.