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

How to pass a structure containing variable-sized array from C# to Fortran DLL?

Mikhail_S_2
Beginner
973 Views

Hello!

I'm trying to establish the interaction between С# application and Fortran DLL using structure marshaling. The main purpose is to pass structure containing a lot of variables including several variable-sized arrays. The problem is that the following code is working in step-by-step debugging mode, but crashes in release mode. Following error is appeared: 

Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

at CSh_DLL_test.Program.PopulateData(myStructure& ms)...

Any help will be appreciated. Codes for the simpliest case are attached below:

C#:

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

namespace CSh_DLL_test
{
class Program
{
// P/Invoke for structure array
[StructLayout(LayoutKind.Sequential)]
public struct myStructure
{
public int size;
public IntPtr inside;
};

[DllImport(@"Fortran_DLL_test.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "PopulateData")]

public static extern void PopulateData(ref myStructure ms);

static void Main()
{
myStructure myS = new myStructure();
myS.size = 10;
int[] arr = new int[myS.size];

IntPtr par = Marshal.AllocHGlobal(Marshal.SizeOf(arr[0]) * myS.size);
myS.inside = par;

PopulateData(ref myS);

for (int i = 0, j = 0; i < arr.Length; i++)
{
arr = Marshal.ReadInt32(myS.inside, j);
j += 4;
}

Marshal.FreeHGlobal(par);
}
}
}

Fortran DLL code:

subroutine PopulateData(user_struct)
implicit none
!DEC$ ATTRIBUTES C, DLLEXPORT :: PopulateData
!DEC$ ATTRIBUTES ALIAS : "PopulateData" :: PopulateData
!DEC$ ATTRIBUTES REFERENCE :: user_struct

type user_structure
integer array_dim
integer, allocatable :: array(:)
end type

type(user_structure) user_struct
integer i

do i=1,user_struct.array_dim-1
user_struct.array(i)=999-i
end do

return
end subroutine PopulateData


0 Kudos
4 Replies
Steven_L_Intel1
Employee
973 Views

Fortran allocatable arrays are not interoperable with any other language. They are certainly not equivalent to a pointer allocated with new. You can use the type C_PTR there (from ISO_C_BINDING) and then the C_F_POINTER intrinsic module subroutine (also from ISO_C_BINDING) to convert that to a Fortran array pointer (not allocatable).

0 Kudos
Mikhail_S_2
Beginner
973 Views

Steve,

Thank you very much for useful advice! Program works properly now.

I have attached code samples for C# and Fortran, may be it will be useful for others.

0 Kudos
Steven_L_Intel1
Employee
973 Views

Good work!  Thanks!

0 Kudos
Morway__Eric
Beginner
973 Views

Mikhail, I see its been about a week since you posted some example files that demonstrate how to pick up some data originally created in C# from Fortran.  I'm attempting to use a mixture of C# and Fortran as well, and so far I haven't had any success.  As this will be my first post on this forum, I'll limit my question to the following until I know you got the message, then I might follow-up a bit more with you.

I was able to compile a solution containing both C# and Fortran projects, where the source code files in each of these projects were what you provided in the forum thread I'm responding to (fortran-dll-test.f90 & programc.txt).  After setting the Fortran project as the "startup project" and dropping a breakpoint in the fortran code, I tried running.  As I mentioned, there were no compiling errors, nor were there any linker errors (I'm working in the visual studio .NET 2010 environment).  However, when I tried to run to the breakpoints, I got the following error message shown below (hopefully the screen capture posted ok?).  I'm guessing that because the fortran project is a DLL, I need to come up with a short "Main" program that calls the "PopulateData" subroutine?  Would you happen to have something like that already?

By the way, thanks for posting the example files, your insight to do so has helped me. 

0 Kudos
Reply