Derived Type from VB to CVF DLL - Getting Wrong Values

Derived Type from VB to CVF DLL - Getting Wrong Values

I have to confess to being a CVF newbie - absolutely no experience of Fortran whatsoever up till a couple of days ago. I desperately need to know what Im doing wrong here.

I create a user defined type in vb and send it to the Fortran dll and then write out the values to file to test that it works - and as you can see it doesnt.

The strange thing is if I just have one 'Double' (Real*8) in my type everything works fine but change one of the other 'single's to a double and they're all out of line in the memory (i'm guessing) but strangley enough the 'Boolean' variables after are ok, and the integer after them is wrong.

(I have tried using the 'pack' and 'sequence' statements without any luck, but to be honest I dont understand them anyway)

If anybody can offer any suggestions/help I would be very grateful.

'Module.bas (Vb6)

Option Explicit

Public Type ggtypeGeometry
ID As Integer
CrackDepth As Single
CrackLength As Single
Thickness As Double
Radius As Double
Eccentricity As Single
Invalid As Boolean
Extrapolation As Boolean
Variation As Integer
End Type

Declare Sub VBtoCVF Lib "c:VBtoCVFVBtoCVF.dll" (ByRef typGeo As ggtypeGeometry)


'Form1.frm (Vb6)

Option Explicit

Private Sub Command1_Click()
Dim Geometry As ggtypeGeometry
With Geometry
.ID = 9
.CrackDepth = 10
.CrackLength = 50
.Thickness = 30
.Radius = 5
.Eccentricity = 2
.Invalid = True
.Extrapolation = False
.Variation = 3
End With
Call VBtoCVF(Geometry)
End Sub


!VBtoCVF.f90 (CVF6.6)

subroutine VBtoCVF (typGeometry)

! Expose subroutine VBtoCVF to users of this DLL
use Type_Global
use dfwin
! Variables

! Body of VBtoCVF
open (16,file = "c:vbToCVF.txt",status = "unknown")

write (16, *) "Info from typGeometry"
write (16,*) "---------------------"
write (16, *) "ID",typGeometry.ID
write (16, *) "CrackDepth",typGeometry.CrackDepth
write (16, *) "CrackLength",typGeometry.CrackLength
write (16, *) "Thickness",typGeometry.Thickness
write (16, *) "Radius",typGeometry.Radius
write (16, *) "Eccentricity",typGeometry.Eccentricity
write (16, *) "Invalid",typGeometry.Invalid
write (16, *) "Extrapolation",typGeometry.Extrapolation
write (16, *) "Variation",typGeometry.Variation


end subroutine VBtoCVF


!Type_Global.f90 (CVF6.6)

module Type_Global

implicit none

type Geometry
integer*2 ::ID
real*4 ::CrackDepth
real*4 ::CrackLength
real*8 ::Thickness
real*8 ::Radius
real*4 ::Eccentricity
logical*2 ::Invalid
logical*2 ::Extrapolation
integer*2 ::Variation
end type Geometry

end module Type_Global


!vbToCVF.txt (values written to file from CVF)

Info from typGeometry
ID 9
CrackDepth 10.
CrackLength 50.00000
Thickness 5.325064510836009E-315
Radius 2.00000047741923
Eccentricity 9.1834095E-41
Invalid T
Extrapolation F
Variation -2348


9 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Use the sequence statement in defining the type in the CVF mod.

I have already tried that but I get a warning that one or more of the variables in the defined type are misaligned and then when I test it I get wrong results.

!Warning after compiling...
!"Warning: The structure contains one or more misaligned fields. [GEOMETRY]"


!In (VB) / Out (CVF) data
!.ID = 9 / 9
!.CrackDepth = 10 / 0.0000000E+00
!.CrackLength = 50 / 2.3362448E-41
!.Thickness = 30 / 8.383305878634271E-320
!.Radius = 5 / 8.125403611505141E-320
!.Eccentricity = 2 / 2.2986900E-41
!.Invalid = True / F
!.Extrapolation = False / T
!.Variation = 3 / 0


Try rearranging your type definition. Put your REAL*8s first, followed by your REAL*4s, followed by your INTEGER*2s and LOGICAL*2s.


Thanks it worked with and without 'sequence'
When I did use 'sequence' I got this warning after compiling
"Warning: The structure length is not a multiple of its largest element; could create misalignments for arrays of this type. [GEOMETRY]"

Is this warning something I should take notice of ?

Plus I would be greatful of an explanation for why I got the right results after placing my variables in size order.

Another thing, how would I make my structure a multiple of its largest variable ?
Is it something to do with 'pack' -ing ?

Thanks again for you help.

Alignment problems of this type can result from differences between the way a caller sets up memory for
a structure and the way the called routine expects the
memory to be set up. This is particular problematic when
mixing languages. For example, if you have a real*4 followed by a real*8 there are a couple of ways that this
might be done. If one supposes that the structure starts on a double word boundary, you could either have the real*8 immediately follow the real*4 in memory, or
you could have the real*4, followed by 4 bytes of padding
then the real*8. The first case takes less memory, but
creates a misalignment since the real*8 wouldn't be on
a double word boundary. The 2nd preserves alignment, which is presumably somewhat more efficient, but wastes
some bytes.

If you change the arrangement so that the real*8 comes
before the real*4, then the issue goes away (unless the
structure is an array), because there is no need to
pad after the real*8, since the next location is a word
boundary, which suits the real*4 just fine.

So, as to the warning about arrays. Now suppose that our
real*8, real*4 example is for an array. Everything works
for the 1st element, but for the 2nd, the real*8
will either be misaligned (on a word boundary instead of
a double word), or the structure will have to be padded
by 4 bytes so that the length of the structure is a
multiple of 8.

There are advantages and disadvantages with each approach. The important thing is that the caller and
callee agree on how it should be done.

Thanks to all for your help its been very useful.

Leave a Comment

Please sign in to add a comment. Not a member? Join today