Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Beginner
67 Views

Calling C# dll from Fortran exe

I have a Fortran exe and a C# DLL.

I'd like to be able to

1) pass a structure from Fortran to C#

2) fill in the values of structure in C#

3) get back the structure in Fortran and print the values

The thread I am using as reference is this - The OP in that post appears to have fixed the issue. But for me, fortran exe crashes as soon as the C# call is made. Trying to avoid COM and/or C++ wrapper approach here. 

I commented out the string variables, thinking that there may be some issue with marshaling them, but to no avail.

Have used 'Unmanaged Exports' to decorate the function in C# so that Fortran can see them. Sure enough, the GetInt() works just fine. It's the GetStruct() that is crashing the app.

What could I be missing here?

C#:

using RGiesecke.DllExport;
using System.Runtime.InteropServices;

namespace CSharpDll
{
    public class Structures
    {
        [DllExport("GetInt", CallingConvention = CallingConvention.Cdecl)]
        public static int GetInt()
        {
            return 123;
        }

        public const int LENSTRING = 200;

        [StructLayout(LayoutKind.Sequential)]
        public struct MyFortranStruct
        {
            public int SourceNode;
            //[MarshalAs(UnmanagedType.ByValArray, SizeConst = 200)]
            //public char[] Title;            
            public int EndNode;
        }

        [DllExport("GetStruct", CallingConvention = CallingConvention.Cdecl)]
        public static void GetStruct(ref MyFortranStruct myStruct)
        {
            MyFortranStruct result = new MyFortranStruct();
            //result.Title = "This is the title, padded to 200 characters just to make sure 345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890".ToCharArray();
            //result.Title = "This is Title #1".PadRight(200).ToCharArray() ;
            result.SourceNode = 123;
            result.EndNode = 321;

            myStruct = result;
        }
    }
}

 

Fortran:

    module InterfacesModule
    use iso_c_binding
    implicit none

    type, bind(c) :: MyFortranStruct
        integer :: SourceNode
        !character :: Title(200)
        integer :: EndNode
    end type

    interface

    function GetInt() bind(C, name="GetInt")
    integer :: GetInt
    end function

    subroutine GetStructSub(stru) bind(C, name="GetStruct")
    import MyFortranStruct
    type(MyFortranStruct), intent(inout) :: stru !, intent(inout) :: stru
!    !DEC$ ATTRIBUTES REFERENCE :: stru
    end subroutine

    end interface
    end module


Finally, the calling portion in Fortran:

    program FortranStructures
    use InterfacesModule

    implicit none
    
    
    
    ! Variables
    type(MyFortranStruct) :: tmpStruct

    ! Body of FortranStructures
    print *, 'Before...'
    
    print *, GetInt()
    !tmpStruct%Title = "Foo"
    !tmpStruct%SourceNode = 999
    !tmpStuct%SourceNode = 888
    call GetStructSub(tmpStruct)
!    print *, tmpStruct%Title
    print *, tmpStruct%SourceNode
    print *, tmpStruct%EndNode
    
    print *, 'After...'

    end program FortranStructures

 

 

 

 

 

 

 

0 Kudos
4 Replies
Highlighted
Beginner
67 Views

Works now. Am now off to calling sqlite wrapped inside C# FROM fortran. exciting!

0 Kudos
Highlighted
Beginner
67 Views

@Sriram r., would you mind posting the code that finally worked for you?  I've done similar work in the past, but more simple that what you were trying to do and would very much like to have access to your working example, if possible?

0 Kudos
Highlighted
New Contributor III
67 Views

@Sriram: I would also like to see the code example that you have working.  I usually call the other direction from a C# method to a Fortran DLL subroutine, so seeing the other way would be very helpful.

Thank you, Greg.

0 Kudos
Highlighted
Beginner
67 Views

attached zip file. again, huge thanks to user bradley from this post.

1) CSharpConsoleApp has logic to create the sqlite db file

2) CSharpDLL is the DLL that will have the logic to be invoked from Fortran

3) FortranStructures is the actual exe file that sends a structure (by reference) to CSharpDLL and gets back the values filled in

0 Kudos