Possible to Pass an Object as a Parameter to a Fortran Method?
I'm currently working on being able to import a DLL written in Fortran into Visual Basic. I've got all the basics down, so now I'm trying to take it a step further. The title basically says it all, but I'll explain what it is I'm trying to do anyways.
For kicks and giggles, let's just assume I want to pass an object that has three double values in it, possibly representing a point in space in three dimensions. In my Fortran m开发者_如何学Pythonethod, I want to take that object, print out the x value, then change the x value to 7.5. Here's my Fortran code that does just that.
module test
type Point
double precision x, y, z
end type Point
end module test
function ex1(ThreeDubs)
use test
type (Point) :: ThreeDubs
print *, ThreeDubs%x
ex1 = 1
return
end function
And this code works great!...For structures only. In other words, Let's assume I have the following structure and class in VB
Public Structure StructurePoint
Public x As Double
Public y As Double
Public z As Double
End Structure
Public Class ObjectPoint
Public x As Double
Public y As Double
Public z As Double
End Class
Creating an instance of StructurePoint yields perfect results: the Fortran method prints out the x value, and then modifies the value of x. Perfect. Now the problem. When I pass an instance of ObjectPoint, the program prints out a value similar to 1.523E-306. Basically, telling me that the location in which it thinks the x value is located is not the x value. So, herein lies my question. Is it even possible to pass an Object to a Fortran DLL and access it correctly, and if so, how would I go about doing so?
The Solution
Modifying the Class declaration is the ONLY thing that has to be done in order to pass this object to Fortran.
<StructLayout(LayoutKind.Sequential)> _
Public Class CustomPoint3d
Public x As Double
Public y As Double
Public z As Double
End Class
<DllImport("passPoint3d.dll")> _
Public Shared Function PrintX(ByVal point As CustomPoint3d) As Boolean
End Function
This might be difficult, and I don't think there's any benefit, so I advise you not to bother!
Here goes anyway! I think the VB.Net object will be marshalled as a pointer. There is some support for pointers in Fortran 90. It might work if you add pointer
to the Fortran declaration of ThreeDubs
.
function ex1(ThreeDubs)
use test
type (Point), pointer :: ThreeDubs ! Note additional pointer keyword
print *, ThreeDubs%x
ex1 = 1
return
end function
I doubt you would ever be able to call methods in the ThreeDubs
object from the Fortran, so I'm not sure of the benefit of passing an object.
Here are two articles on PInvoke: PInvoke is the .Net name for calling oldschool "unmanaged" DLLs like your Fortran. The articles explain how .Net arguments are "marshalled" (translated) into the Fortran DLL. You have some control over the marshalling using attributes: the articles explain more. They tend to use C and C# for examples :(
I don't know about Visual Basic, but I've shared user-defined types between Fortran & C. This is supported by the ISO C Binding of Fortran 2003, which is already widely supported by Fortran 95 compilers. You declare a Fortran user-defined type and give it the bind C attribute and a bind name. As long as all of the sub-components of the type are inter-operable with C, then the user-defined type is also inter-operable with C. And this method is standard and portable. I've done this by passing the information with the Fortran user-defined type variable being a module variable, and the C structure variable being in global memory via being declared at the top of a file. Perhaps you can use the ISO C Binding on the Fortran side, and somehow tell Visual Basic to use a C-like interface?
精彩评论