C# read the values of a Fortran 95 type/struct?

R

RaleighDan

I would like to know how to have C# read the values of a Fortran 95
type/struct. Is this possible? The code I have currently is not
working. I have scoured the web trying to find some direction with no
luck. Any ideas?

Here is what I have as the Fortran DLL code:

! employee.f90
!
! FUNCTIONS/SUBROUTINES exported from employee.dll:
! employee - subroutine
!
module employee
use iso_c_binding

! Variables

! Body of employee

type, bind(C) :: employee_type
character(12) :: emplid
character(8) :: emplpermnum
character(50) :: empladdr
character(50) :: emplcity
character(2) :: emplstate
character(10) :: emplzip
end type employee_type

contains

function new_employee() bind(C)
! Expose function new_employee to users of this DLL

!DEC$ ATTRIBUTES DLLEXPORT::new_employee
type(C_PTR) :: new_employee
type(employee_type), pointer :: new_emp
allocate(new_emp)

! Fill in fields...
new_emp%emplid = 'ABCDEFG'
new_emp%emplpermnum = '123456'
new_emp%empladdr = '789 main street'
new_emp%emplcity = 'San Diego'
new_emp%emplstate = 'CA'
new_emp%emplzip = '92124'

! Convert Fortran pointer to C pointer
new_employee = c_loc(new_emp)
! Return pointer to new_employee
return
end function new_employee

end module employee




And here is the C# code

[DllImport("employee.dll", EntryPoint = "new_employee",
CallingConvention = CallingConvention.Cdecl)]so the class looks like
this now:<pre name="code" class="c-sharp">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApp
{
class Program
{

[DllImport("employee.dll", EntryPoint = "new_employee",
CallingConvention = CallingConvention.Cdecl)]
private static extern void new_employee();

[StructLayout(LayoutKind.Sequential)]
public struct employee_type
{
public string strEmplid;
public string strEmplpermnum;
public string strEmpladdr;
public string strEmplcity;
public string strEmplstate;
public string strEmplzip;

}

static void Main(string[] args)
{

employee_type et = new employee_type();

new_employee();

Console.WriteLine(et.strEmplid);
Console.WriteLine(et.strEmpladdr);
}
}
}
 
R

RaleighDan

Thanks Peter,
That worked perfectly! Leaving the Fortran code just as it was I was
able to use the following C# code based on your "template":


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApp
{
class Program
{

[DllImport("employee.dll", EntryPoint = "new_employee",
CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr new_employee();

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct employee_type
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 12)]
public string strEmplid;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
public string strEmplpermnum;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
public string strEmpladdr;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
public string strEmplcity;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)]
public string strEmplstate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string strEmplzip;

}


static void Main(string[] args)
{

employee_type et = (employee_type)Marshal.PtrToStructure
(new_employee(), typeof(employee_type));

Console.WriteLine("Employee ID: \"" + et.strEmplid +
"\"");
Console.WriteLine("Employee Permit Number: \"" +
et.strEmplpermnum + "\"");
Console.WriteLine("Employee Address: \"" + et.strEmpladdr
+ "\"");
Console.WriteLine("Employee City: \"" + et.strEmplcity +
"\"");
Console.WriteLine("Employee State: \"" + et.strEmplstate +
"\"");
Console.WriteLine("Employee Zip: \"" + et.strEmplzip +
"\"");

}
}
}




Again, thanks for your time and assistance.

--Dan
 
R

RaleighDan

Thanks Peter,
That worked perfectly! Leaving the Fortran code just as it was I was
able to use the following C# code based on your "template":


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApp
{
class Program
{

[DllImport("employee.dll", EntryPoint = "new_employee",
CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr new_employee();

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct employee_type
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 12)]
public string strEmplid;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
public string strEmplpermnum;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
public string strEmpladdr;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
public string strEmplcity;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)]
public string strEmplstate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string strEmplzip;

}


static void Main(string[] args)
{

employee_type et = (employee_type)Marshal.PtrToStructure
(new_employee(), typeof(employee_type));

Console.WriteLine("Employee ID: \"" + et.strEmplid +
"\"");
Console.WriteLine("Employee Permit Number: \"" +
et.strEmplpermnum + "\"");
Console.WriteLine("Employee Address: \"" + et.strEmpladdr
+ "\"");
Console.WriteLine("Employee City: \"" + et.strEmplcity +
"\"");
Console.WriteLine("Employee State: \"" + et.strEmplstate +
"\"");
Console.WriteLine("Employee Zip: \"" + et.strEmplzip +
"\"");

}
}
}




Again, thanks for your time and assistance.

--Dan
 
B

Ben Voigt [C++ MVP]

RaleighDan said:
Thanks Peter,
That worked perfectly! Leaving the Fortran code just as it was I was
able to use the following C# code based on your "template":

But now you have a memory leak.

You also need to give that IntPtr back to the Fortran DLL and have it
perform whatever undoes allocate+c_loc
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApp
{
class Program
{

[DllImport("employee.dll", EntryPoint = "new_employee",
CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr new_employee();

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct employee_type
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 12)]
public string strEmplid;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
public string strEmplpermnum;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
public string strEmpladdr;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
public string strEmplcity;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)]
public string strEmplstate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string strEmplzip;

}


static void Main(string[] args)
{

employee_type et = (employee_type)Marshal.PtrToStructure
(new_employee(), typeof(employee_type));

Console.WriteLine("Employee ID: \"" + et.strEmplid +
"\"");
Console.WriteLine("Employee Permit Number: \"" +
et.strEmplpermnum + "\"");
Console.WriteLine("Employee Address: \"" + et.strEmpladdr
+ "\"");
Console.WriteLine("Employee City: \"" + et.strEmplcity +
"\"");
Console.WriteLine("Employee State: \"" + et.strEmplstate +
"\"");
Console.WriteLine("Employee Zip: \"" + et.strEmplzip +
"\"");

}
}
}




Again, thanks for your time and assistance.

--Dan
 
B

Ben Voigt [C++ MVP]

RaleighDan said:
Thanks Peter,
That worked perfectly! Leaving the Fortran code just as it was I was
able to use the following C# code based on your "template":

But now you have a memory leak.

You also need to give that IntPtr back to the Fortran DLL and have it
perform whatever undoes allocate+c_loc
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApp
{
class Program
{

[DllImport("employee.dll", EntryPoint = "new_employee",
CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr new_employee();

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct employee_type
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 12)]
public string strEmplid;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
public string strEmplpermnum;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
public string strEmpladdr;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
public string strEmplcity;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)]
public string strEmplstate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string strEmplzip;

}


static void Main(string[] args)
{

employee_type et = (employee_type)Marshal.PtrToStructure
(new_employee(), typeof(employee_type));

Console.WriteLine("Employee ID: \"" + et.strEmplid +
"\"");
Console.WriteLine("Employee Permit Number: \"" +
et.strEmplpermnum + "\"");
Console.WriteLine("Employee Address: \"" + et.strEmpladdr
+ "\"");
Console.WriteLine("Employee City: \"" + et.strEmplcity +
"\"");
Console.WriteLine("Employee State: \"" + et.strEmplstate +
"\"");
Console.WriteLine("Employee Zip: \"" + et.strEmplzip +
"\"");

}
}
}




Again, thanks for your time and assistance.

--Dan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top