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

Fortran DLL Callable From C#?

Bradley_P_1
Beginner
1,248 Views

I learned Fortran last millennium, but haven't used it regularly for several decades, and certainly not in a more modern context.  I now find myself in an environment with a lot of good, legacy code that I need to be able to interact with.  To that end, I'd like to be able to turn at least some of the code into DLLs for referencing from C# applications.  This interaction will be a learning process for me, especially given that we will need to exchange somewhat complex data structures.  However, the first step is getting a simple DLL working.

I found a simple and excellent article at https://software.intel.com/en-us/articles/calling-fortran-function-or-subroutine-in-dll-from-c-code that appears to give me exactly what I need.  Unfortunately, however, when I attempt to run it I get the following:

  • Unable to find an entry point named 'FSUB' in DLL 'FortranDLL01.dll'

I'm sure it's something trivial I'm doing wrong, possibly even some compiler switches, but I'm at a loss.  Any help would be much appreciated!

Thanks!

Brad.

0 Kudos
1 Solution
FortranFan
Honored Contributor III
1,248 Views

See this thread, especially the attachments with Message #2:

https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/509148

Of course, the case in the above thread is with Visual Basic, but as you know, in the .NET world, you can easily apply the same concepts to C# as shown with Visual Basic; the Fortran code remains the same.

View solution in original post

0 Kudos
8 Replies
FortranFan
Honored Contributor III
1,249 Views

See this thread, especially the attachments with Message #2:

https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/509148

Of course, the case in the above thread is with Visual Basic, but as you know, in the .NET world, you can easily apply the same concepts to C# as shown with Visual Basic; the Fortran code remains the same.

0 Kudos
Bradley_P_1
Beginner
1,248 Views

PERFECT!!!  Thank-you FortranFan!

Brad.

P.S.  I expect you'll be hearing more from me, but I think I'm good to go for now.  :-)

0 Kudos
Greg_T_
Valued Contributor I
1,248 Views

Hi Brad,

Calling Fortran routines from C# has worked very well for our fracture mechanics software.  We use C# for the GUI to gather the input data, and then call the Fortran routines to do the engineering calculations, and then return results to display in the C# GUI like data grids, charts, pictures, etc.

I've found that it is very helpful to write a text log file from the Fortran routines to check that values are passed correctly, list intermediate calculations, and any warnings or errors.  We pass a log file flag and file name string from the C# to the Fortran so that we can turn the log file on and off at run-time.  We also pass a flag and string back from the Fortran routines that contains any warning or error information, so that it can be displayed in the GUI.

I've found one item that is different for a Fortran DLL than an EXE is the local allocatable arrays staying in memory.  To be able to reenter a Fortran DLL routine again for another calculation, it is important to deallocate any local allocatable arrays when exiting the Fortran so that the arrays are left as deallocated for the next call.  Or at least check the allocation status before trying to allocate again.

Regards,
Greg Thorwald

0 Kudos
Bradley_P_1
Beginner
1,248 Views

Greg:

That is exactly our scenario.  I'm putting a C# GUI on a Fortran engine and I need to pass variables back and forth.  Previously we've accomplished this by compiling the Fortran engine as an executable and passing text files back and forth.  However, we are now doing some work on our data model and it feels as though converting the engine to a DLL and passing structures back and forth would be a better way to go.  We have too much code tied up in writing and parsing text files.

Thanks for the tips!  I'm sure I'll be back to ask more questions about data structures as I get into this more.

Brad.

0 Kudos
Bradley_P_1
Beginner
1,248 Views

Come to think of it, you could probably all save me a LOT of time if there were an example similar to the one above for interacting that also showed passing somewhat complex structures back and forth.  I'd like to send a structure consisting of a variety of integers, reals, arrays, and strings to my engine, and return a different structure back to the caller.  I'll be picking my way through this, but if there were a good example to follow, that would certainly help me along and save me a lot of time.

Thanks!

Brad.

0 Kudos
FortranFan
Honored Contributor III
1,248 Views

Bradley P. wrote:

Come to think of it, you could probably all save me a LOT of time if there were an example similar to the one above for interacting that also showed passing somewhat complex structures back and forth. ..

See this thread for another example in Message #5, 

https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/474309

Note the above example is somewhat outdated; I'd now get rid of all !DEC$ ATTRIBUTE stuff and simply go with BIND(C) feature as shown in the example with Message #2 in this topic for both the Fortran procedure as well as the derived type.

It looks like you have fairly significant changes in mind for your code.  Given that, there is only so much time you should consider saving - rather you should plan on putting in some hard yards to pick up what options are available to you in modern Fortran and how you best you can make use of them in conjunction with your C# code.  Forums like this can simply give you some go-by's and pointers.  Only you can know your specific needs, requirements and design architecture, etc.  One suggestion would be to review some material in Dr Fortran blog here: https://software.intel.com/en-us/blogs/2013/12/30/doctor-fortran-in-its-a-modern-fortran-world

All the sources in the blog above have sections on standard C interoperability features in Fortran.  You can make use of them on your Fortran DLL side and then have your C# code use P/Invoke layer the same as one would with C DLLs.  

0 Kudos
Greg_T_
Valued Contributor I
1,248 Views

Hi Brad,

Another detail I remembered about C# calling Fortran is that multi-dimensional arrays need to be transposed, since C# uses row order and Fortran uses column order.  I'll either create the array in C# already transposed by swapping the row and column dimensions, or use the .Transpose() method on the array.  Here is a reference with information and examples that I found to be useful:

http://www.nag.co.uk/numeric/csharpinfo.asp

Regards,
Greg

0 Kudos
Michael_R_7
Beginner
1,248 Views

Hi Brad,

I went through this process a few years back, taking a Fortran exe and converting to a dll for a C# front end. I would strongly suggest having a wrapper/ intermediate interop layer - this will allow you to change your c# or fortran data layout without breaking everything. Although passing structs is possible I prefer to stick with nice simple types, especially as you may potentially want different data on each side. Having a wrapper also keeps all your dll imports etc nicely together, keeps you C# code looking much cleaner (all the passing by reference looks ugly to me) and means you can use the Fortran dll from different programs if you want without repeating all the interop in two projects. 

As Greg pointed out there are a few things to watch out for. Making sure any units (eg log files) are correctly closed, arrays deallocated, variables initialized (if assuming they will be zero on the first call). If you enable native code debugging on the C# project you can at debug the Fortran code to help find these. Be very careful if there are any pointers as failure to explicitly deallocate these will result in memory leak (if the process was going to end anyway lazy programmers might not bother to do a clear up - but in a dll situation where the process runs many times longer you could have problems!)

Another tip would be watch out for any STOP statements - these will stop the whole process including the C# front end! The legacy code I had made liberal use of these for error handling and jumping out of deeply nested routines. If you need to do this try throwing an exception in Fortran and catching it in the c# code instead using

SUBROUTINE ThrowException()
    USE Kernel32
    CALL RaiseException(EXCEPTION_NONCONTINUABLE_EXCEPTION, 0, 0, 0)
END SUBROUTINE ThrowException

(you'll have to add the HandleProcessCorruptedStateExceptions attribute to the c# routine).

Good luck!

Michael 

0 Kudos
Reply