PDA

View Full Version : A simple .NET assembly


cubud
06-04-2004, 08:26 AM
Hi all

I am not a Fortran programmer at all, but I have been charged with the task of checking the possibility of interfacing some old Fortran77 subroutines with C#.

I was wondering if anyone would be kind enough to post a simple example of a class which exports

REAL*4 REALNUMBERS(10)
CHARACTER*4 ERRORCODE
CHARACTER*80 MESSAGES(10)

I would be very grateful, thank you.

Pete

tzeis
06-04-2004, 06:13 PM
If you want to create a class from the Fortran code using the .NET Fortran compiler, then no export is needed, you just use the Fortran defined namespace and instantiate the Fortran class like any other .NET compatible class. This is the easiest way to go, because you can convert the Fortran character variables to unicode String variables using the USTRING intrinsic function.
To call the Fortran code from a DLL is a bit more of a problem, because you would be responsible for converting the Fortran character variables, probably by creating your own marshalling procedure in C#. We have not done this, and don't have any examples of passing unicode String data to a Win32 DLL.

cubud
06-04-2004, 08:15 PM
Hi

Sorry, "export" was an inappropriate word. If I were talking C# I would say "a method which returns"

Pete

tzeis
06-07-2004, 10:06 PM
If you want to pass the data as arguments, the code might look something like this:

subroutine mysub(r1,s1,s2)
use System
real :: r1
type (String), pointer :: s1, s2(:)
character(4) :: c1
character(80) :: c2(10)
c1 = string(s1)
c2 = string(s2)
! do stuff
end subroutine


On the C# side, the subroutine would be referred to as mysub%mysub(...), data types would be float and String.

You could also use properties to convert between the Fortran Character type and the System.String type. Here is what a Fortran class that makes Fortran data available to C# as properties might look like:


module MyNamespace
use System
type datatypes
real, private :: REALNUMBERS(10)
character(len=4), private :: ERRORCODE
character(len=80), private :: MESSAGES(10)
contains
property, pass :: RealNumbers => get_RealNumbers, set_RealNumbers
property, pass :: ErrorCode => get_ErrorCode, set_ErrorCode
property, pass :: Message => get_Message, set_Message
end type
contains
function get_RealNumbers(this) result(res)
type(datatypes) :: this
real :: res(10)
res = this%REALNUMBERS
end function
function get_ErrorCode(this) result(res)
type(datatypes) :: this
type (String), pointer :: res
res => ustring(this%ERRORCODE)
end function
function get_Message(this,i) result(res)
type(datatypes) :: this
type (String), pointer :: res
integer :: i
res => ustring(this%MESSAGES(i))
end function
subroutine set_RealNumbers(this,Num)
type(datatypes) :: this
real :: Num(10)
this%REALNUMBERS = Num
end subroutine
subroutine set_ErrorCode(this,Code)
type(datatypes) :: this
type (String), pointer :: Code
this%ERRORCODE = string(Code)
end subroutine
subroutine set_Message(this,i,Mes)
type(datatypes) :: this
type (String) :: Mes
integer :: i
this%MESSAGES(i) = string(Mes)
end subroutine
end module


The "xet_RealNumbers" and "xet_ErrorCode" methods are properties, and the "xet_Message" methods are indexers.