View previous topic :: View next topic |
Author |
Message |
mposhptti
Joined: 01 May 2008 Posts: 7
|
Posted: Wed May 07, 2008 10:20 am Post subject: Access a Fortran Module variable from within Visual Basic? |
|
|
Does the statement:
"Fortran data that appears in a MODULE or COMMON block is also defined as static data. This means for example that an executable and a library cannot share this kind of data. This is analogous to the situation on a Win32 platform where (by default) a Fortran executable cannot share this kind of data with a DLL."
which is located in the help:
ms-help://MS.VSCC.v80/MS.VSIPCC.v80/Silverfrost.FTN95Help/FTN95Help/HTML/NETPROG/FortranInAnOOEnv.htm
mean that a Fortran variable in a Fortran Module is not directly accessible from within Visual Basic? By directly, I mean that I couldn't have something like the following:
Fortran Code---------------------
MODULE MOD1
real :: Real1Save
END MODULE MOD1
!
Subroutine sub1_fort(real1)
USE MOD1
ASSEMBLY_INTERFACE(NAME="Sub1")
real, intent (inout) :: real1
Real1Save = real1
real1 = real1 + 10.
RETURN
END SUBROUTINE sub1_fort
Visual Basic Code-----------------
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim real1 As Single
real1 = 1.5F
Call fortran.Sub1(real1)
real1 = fortran.MOD1.Real1Save
End Sub
End Class
Note: The CONTAINING_CLASS for the Fortran project is "fortran".
The red code above does not compile, but that is what I would like to do. I have tried making the Real1Save variable a VB object with something like:
OBJECT ("System.Single") :: Real1Save
but that didn't seem to work. If there is a direct (i.e., other that passing the variable as an argument) way to do the above, how would that be done? |
|
Back to top |
|
|
Andrew
Joined: 09 Sep 2004 Posts: 232 Location: Frankfurt, Germany
|
Posted: Wed May 07, 2008 11:33 am Post subject: |
|
|
Modules are not exposed in the same object orientated way as objects in other .NET languages. Aside from passing the variables as arguments - you could provide accessor methods (as you would if they were private variables in VB .NET or C# etc.) like so:
Code: |
MODULE MOD1
REAL :: REAL1SAVE
END MODULE MOD1
SUBROUTINE SUB1_FORT(REAL1)
USE MOD1
ASSEMBLY_INTERFACE(NAME="Sub1")
REAL, INTENT (INOUT) :: REAL1
REAL1SAVE = REAL1
REAL1 = REAL1 + 10.
RETURN
END SUBROUTINE
! Accessor for Real1Save
REAL FUNCTION GETREAL1SAVE()
USE MOD1
ASSEMBLY_INTERFACE(NAME="MOD1_GetReal1Save")
GETREAL1SAVE = REAL1SAVE
END FUNCTION
|
and calling code (in C#):
Code: |
float f = 2.0F;
float ret;
FortranApplication7.Sub1(ref f);
Console.WriteLine(f);
ret = FortranApplication7.MOD1_GetReal1Save();
Console.WriteLine(ret);
Console.ReadKey();
|
Giving the correct output of:
|
|
Back to top |
|
|
mposhptti
Joined: 01 May 2008 Posts: 7
|
Posted: Wed May 07, 2008 2:12 pm Post subject: |
|
|
Andrew,
Thank you for the response. I tried using the accessor method in visual basic and that worked. Are there any plans to implement the exposing of Fortran Modules "in the same object orientated way as objects in other .NET languages?"
Thank you,
matt |
|
Back to top |
|
|
Andrew
Joined: 09 Sep 2004 Posts: 232 Location: Frankfurt, Germany
|
Posted: Wed May 07, 2008 8:57 pm Post subject: |
|
|
We had a decision to make when implementing Fortran for .NET - we could expose Fortran in the same way as object orientated languages and make compromises on the amount of standard Fortran support - or we could keep full language support for Fortran and provide an interface to .NET alongside this. We chose to opt for the latter, as it means that normal Fortran code, including all legacy code, can be used with .NET and Fortran, after all, is not object orientated.
That is basically the long way of saying no, there are no plans to expose module information in the way you describe. |
|
Back to top |
|
|
mposhptti
Joined: 01 May 2008 Posts: 7
|
Posted: Wed May 07, 2008 9:22 pm Post subject: |
|
|
Thank you.
To draw a comparison, Lahey did choose to expose Fortran in the same way and thus has some limitations on what standard Fortran is supported and may also be why they have not developed beyond VS2003 (.NET Framework 1.1).
So, just to make sure, is there any "slick" way to reference variables directly in both VB and Fortran without having to use an Accessor? Maybe by creating a VB class and adding it as a reference so that in both the VB and Fortran I could reference and modify the same variable with something like: modNamespace.modClass.REAL1SAVE? The Accessor method is not efficient when there are thousands of variables in modules.
Thank you again,
matt |
|
Back to top |
|
|
Andrew
Joined: 09 Sep 2004 Posts: 232 Location: Frankfurt, Germany
|
Posted: Wed May 07, 2008 10:55 pm Post subject: |
|
|
There is one other way that this can be achieved which may be closer to what you would like, but you will still have to write some extra code to achieve it. Consider three projects, a C# executable, a C# library and a Fortran library. First the C# library:
Code: |
namespace MyNamespace
{
public class MyClass
{
private int _i;
public int I
{
get { return _i; }
set { _i = value; }
}
}
}
|
All this does is declare a class with one private variable and provides an accessor for it (making it a .NET property of course). This must be created as a property and not simply as a public variable. This does mean that you will need to implement properties for all variables you wish to expose. In Visual Studio 2005/2008 (at least for C#) you can select private variables, and using the refactor tool can automatically create properties for you.
VB code would look something like (and it looks like there is no refactor tool for VB .NET):
Code: |
Public Class MyClass
Private _i As Integer
Public Property I() As Integer
Get
Return _i
End Get
Set(ByVal Value As Integer)
_i = Value
End Set
End Property
End Class
|
Next the Fortran:
Code: |
! A module to store a reference to our .NET object
MODULE MOD1
REAL :: REAL1SAVE
OBJECT("MyNamespace.MyClass") :: OBJSAVE
END MODULE MOD1
! A routine that changes the value of the property contained
! within the stored object, note the use of OBJSAVE%I
SUBROUTINE DOSOMETHING()
USE MOD1
ASSEMBLY_INTERFACE(NAME="DoSomething")
! It is possible to set *properties* of .NET objects using the
! % operator
OBJSAVE%I = 21
END SUBROUTINE
! Routine to store an instance of the .NET object
SUBROUTINE SETREF(OBJ)
USE MOD1
ASSEMBLY_INTERFACE(NAME="SetRef")
OBJECT("MyNamespace.MyClass") :: OBJ
OBJSAVE = OBJ
END SUBROUTINE
|
You can see the routine SETREF, which is used to store an instance of the C# class defined above. Also within DOSOMETHING, we set the value of a property by using the % operator. This is only allowed on properties of .NET objects that have corresponding Fortran types.
And finally the executable code:
Code: |
MyClass testClass = new MyClass();
testClass.I = 7;
Console.WriteLine(testClass.I);
FortranApplication.SetRef(testClass);
FortranApplication.DoSomething();
Console.WriteLine(testClass.I);
Console.ReadKey();
|
This bit of code creates an instance of the .NET class MyClass and passes it to SetRef within the Fortran. We then call DoSomething in the Fortran which sets the property within MyClass to a different value. The following gives the output:
Which demonstrates how the Fortran has modified the property of the object which both the C# executable and the Fortran have reference to.
If the Fortran code was to be the main executable you could create the instance of the .NET class by using object creation code in the Fortran (see NEW@ and OBJECT) and passing this to the .NET code (see ASSEMBLY_EXTERNAL).
This behaviour about accessing properties is in the documentation in the section titled .NET Platform -> .NET Programming -> Manipulating .NET Objects. |
|
Back to top |
|
|
mposhptti
Joined: 01 May 2008 Posts: 7
|
Posted: Thu May 08, 2008 3:07 am Post subject: |
|
|
Thank you!!! I have that working now with VB and Fortran. I added another Fortran subroutine and a few more lines on the VB side to test multiple changes to the variable from multiple routines and everything worked great. Now I have to digest it and evaluate the feasability of implementing this on a large-scale. |
|
Back to top |
|
|
mposhptti
Joined: 01 May 2008 Posts: 7
|
Posted: Thu May 08, 2008 3:59 pm Post subject: |
|
|
Quote: | (and it looks like there is no refactor tool for VB .NET) |
There is a refactor tool for VB.NET. It can be found at:
http://www.devexpress.com/Products/NET/IDETools/VBRefactor/
For example, it will refactor:
Code: | PUBLIC I As Integer |
To
Code: | Private _i As Integer
Public Property I() As Integer
Get
Return _i
End Get
Set(ByVal value As Integer)
_i = value
End Set
End Property |
|
|
Back to top |
|
|
|