Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29271 Discussions

C# and Intel Fortran V11 - Passing of Strings

thundurstruck
Beginner
446 Views
Hi Fortran Gurus - Long time fortran programmer, first time integration with C#. I've built a dll with the following subroutine in it:

SUBROUTINE GET_NAME(PC_NUM, PC_STRING)

!DEC$ ATTRIBUTES DLLEXPORT::get_name
!DEC$ ATTRIBUTES DECORATE, ALIAS:'get_turbine_name'::get_name

INTEGER PC_NUM
CHARACTER*256, INTENT(OUT) :: PC_STRING

PC_STRING='UNKNOWN - NOT AVAILABLE'
IF(PC_NUM.EQ.1) PC_STRING='CLASS I'
IF(PC_NUM.EQ.2) PC_STRING='CLASS II'
IF(PC_NUM.EQ.3) PC_STRING='CLASS III'
IF(PC_NUM.EQ.4) PC_STRING='CLASS IV'

END SUBROUTINE

Here is the current interface I have in C# to call it:
[DllImport("test.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern void get_name(
int number,
StringBuilder strb, int strlen);

static void Main(string[] args)
{
int mynum = 1;
int strlen = 0;
StringBuilder name_turbine = new StringBuilder();
Console.WriteLine("Starting Test Program");
get_turbine_name(num_turbine, name_turbine, strlen);

I'm recieving the following error in C#:
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

Has anyone encountered this error before? I've been working on this for a few hours now without any luck.
Thanks much for any advice you can provide.

0 Kudos
2 Replies
Xiaoping_D_Intel
Employee
446 Views
Quoting - thundurstruck
Hi Fortran Gurus - Long time fortran programmer, first time integration with C#. I've built a dll with the following subroutine in it:

SUBROUTINE GET_NAME(PC_NUM, PC_STRING)

!DEC$ ATTRIBUTES DLLEXPORT::get_name
!DEC$ ATTRIBUTES DECORATE, ALIAS:'get_turbine_name'::get_name

INTEGER PC_NUM
CHARACTER*256, INTENT(OUT) :: PC_STRING

PC_STRING='UNKNOWN - NOT AVAILABLE'
IF(PC_NUM.EQ.1) PC_STRING='CLASS I'
IF(PC_NUM.EQ.2) PC_STRING='CLASS II'
IF(PC_NUM.EQ.3) PC_STRING='CLASS III'
IF(PC_NUM.EQ.4) PC_STRING='CLASS IV'

END SUBROUTINE

Here is the current interface I have in C# to call it:
[DllImport("test.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern void get_name(
int number,
StringBuilder strb, int strlen);

static void Main(string[] args)
{
int mynum = 1;
int strlen = 0;
StringBuilder name_turbine = new StringBuilder();
Console.WriteLine("Starting Test Program");
get_turbine_name(num_turbine, name_turbine, strlen);

I'm recieving the following error in C#:
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

Has anyone encountered this error before? I've been working on this for a few hours now without any luck.
Thanks much for any advice you can provide.


By default scalar type like integer is passed by reference in fortran so its corresponding in C# should be declared as reference type.Moreover, the string passed back to C# should be null-terminated.


SUBROUTINE GET_NAME(PC_NUM, PC_STRING)

!DEC$ ATTRIBUTES DLLEXPORT::get_name
!DEC$ ATTRIBUTES DECORATE, ALIAS:'get_turbine_name'::get_name

INTEGER PC_NUM
CHARACTER*256, INTENT(OUT) :: PC_STRING

PC_STRING='UNKNOWN - NOT AVAILABLE' // char(0)
IF(PC_NUM.EQ.1) PC_STRING='CLASS I' // char(0)
IF(PC_NUM.EQ.2) PC_STRING='CLASS II' // char(0)
IF(PC_NUM.EQ.3) PC_STRING='CLASS III' // char(0)
IF(PC_NUM.EQ.4) PC_STRING='CLASS IV' // char(0)

END SUBROUTINE




[DllImport("test.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern void get_name(
ref int number,
StringBuilder strb, int strlen);

static void Main(string[] args)
{
int mynum = 1;
int strlen = 0;
StringBuilder name_turbine = new StringBuilder(256);
strlen = 256;
Console.WriteLine("Starting Test Program");
get_turbine_name(ref num_turbine, name_turbine, strlen); // "num_turbine" should be mynum???
..


0 Kudos
thundurstruck
Beginner
446 Views

By default scalar type like integer is passed by reference in fortran so its corresponding in C# should be declared as reference type.Moreover, the string passed back to C# should be null-terminated.


SUBROUTINE GET_NAME(PC_NUM, PC_STRING)

!DEC$ ATTRIBUTES DLLEXPORT::get_name
!DEC$ ATTRIBUTES DECORATE, ALIAS:'get_turbine_name'::get_name

INTEGER PC_NUM
CHARACTER*256, INTENT(OUT) :: PC_STRING

PC_STRING='UNKNOWN - NOT AVAILABLE' // char(0)
IF(PC_NUM.EQ.1) PC_STRING='CLASS I' // char(0)
IF(PC_NUM.EQ.2) PC_STRING='CLASS II' // char(0)
IF(PC_NUM.EQ.3) PC_STRING='CLASS III' // char(0)
IF(PC_NUM.EQ.4) PC_STRING='CLASS IV' // char(0)

END SUBROUTINE




[DllImport("test.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern void get_name(
ref int number,
StringBuilder strb, int strlen);

static void Main(string[] args)
{
int mynum = 1;
int strlen = 0;
StringBuilder name_turbine = new StringBuilder(256);
strlen = 256;
Console.WriteLine("Starting Test Program");
get_turbine_name(ref num_turbine, name_turbine, strlen); // "num_turbine" should be mynum???
..




Xiaoping - Thank you very much for your suggestion. It worked very well.


0 Kudos
Reply