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

Error Trapping between C# and Fortran DLL

Ibrahim_A_
Novice
4,564 Views

I have a Fortran DLL code that includes a lot of modules. The DLL is called by a C# code. I am trying to make the program exit gracefully without crashing if an error is encountered on the Fortran side. Also, I'd like to send error messages back to the C# side.

I am aware from some research that error trapping has been an issue between C# and Fortran. But, is there any update on that? Can the most recent compilers trap errors in Fortran between C# and Fortran?

0 Kudos
41 Replies
Steve_Lionel
Honored Contributor III
2,729 Views

There is no exception handling in Fortran. You may have options depending on what sort of error you want to trap. Some of them get raised and propagate normally, some get "handled" by the Fortran run-time library according to the severity and type. 

Are you looking to trap ANY kind of error, or are there specific ones you are worried about? You should have a careful read of the section Handling Run-Time Errors in the Intel Fortran documentation.

0 Kudos
Ibrahim_A_
Novice
2,713 Views

@Steve_Lionel ,

I was originally looking for handling or propagating any kind of error. But since there are limited options, what are the types of errors that can be trapped between C# and Fortran? And where is that included in the documentation?

Thanks!

0 Kudos
Steve_Lionel
Honored Contributor III
2,710 Views

I have no personal experience playing with this sort of thing. I would expect you'd have more success from processor-raised exceptions (floating overflow, etc.) and less from I/O errors. The link I provided is under Compiler Reference > Error Handling.

Intel Fortran does not create exception-propagating stack frames. I don't know well this will work for you.

0 Kudos
JohnNichols
Valued Contributor III
2,702 Views

The first good error trapping was continuations in LISP Compilers, which were an excellent idea.  But the error trapping you see in C# is just not available in Fortran.  LISP is perfect except that it is a turtle with speed and a beast to learn. 

I do a lot of work in both -- but they are really not that compatible, they are close really -- but the error handling for C# is more like LISP Conts and Fortran just &^%*&

0 Kudos
Greg_T_
Valued Contributor I
2,675 Views

We have engineering programs with a C# GUI that call Fortran DLLs for the calculations.  In the C# code, I put the call to the Fortran subroutine inside a try-catch block that catches any un-caught errors in the Fortran.  In the Fortran subroutines, we've included if-statements to check for errors, such as division by zero, square-root of negative values, etc. before doing the calculation.  If such an error is found by our if-statements we exit the routine, deallocate local arrays, and return an integer error code and string with a useful message back to the C# code to display to the user.  The user can then hopefully understand what input to change and then run the analysis again.  By deallocating local arrays in the Fortran DLL on exit, the user can re-run after changing the input data without needing to exit the program.  This approach does require adding if-statements to check data before an error might occur, but this has worked well for us.

Regards, Greg T.

0 Kudos
JohnNichols
Valued Contributor III
2,671 Views

Yes that is the perfect soln - the only problem is catching all the error types -- there is always one you missed.  

But that is also the difference between commercial and academic code -- we can cheat 

0 Kudos
Ibrahim_K_
New Contributor I
2,591 Views

I am just about to finish a similar project. I will provide some of the lessons I learned.

Firstly, I link my FORTRAN code with native C++ to generate a static library. Then I wrap the static library in a C++/CLI code. Calls between C# and CLI are managed calls. You can pass any info between like you are within C#. I uploaded here in this forum my project architecture sometimes ago. 

1) I do not do anything fancy with memory on the FORTRAN side. If I need play with memory, I do it in C++. You can pass std::vector structures to FORTRAN safely.

2) I turned on the Intel Compiler option to check all subroutine parameters. I forgot how I did it but Steve may be able point out again.

3) I do not do any fancy I/O in FORTRAN.

Since things like division by zero do not produce exceptions (in the sense that FORTRAN generated code continues with "Nan" value), you can check them at a later point or even display it. I had no crashes in the last two years on the FORTRAN side. My initial problems were related to memory (mismatched commons) and incorrrect subroutine call list.

Good luck.

I. Konuk

 

0 Kudos
Ibrahim_A_
Novice
2,572 Views

@Ibrahim_K_ 

Thank you Ibrahim!

Can you share an example or point me to the link to your post that describes the architecture?

0 Kudos
Ibrahim_A_
Novice
2,566 Views

@Steve_Lionel 

When I enabled the "Check for unallocated arrays" for Process-raised errors and an error takes place, I get an error message but the program crashes after I hit okay on the error message. Is there a way to gracefully exit the program after this kind of error takes place?

0 Kudos
Arjen_Markus
Honored Contributor I
2,559 Views

You should realise that using unallocated arrays is always an error in your program: you should allocate them first, before attempting to set an element or examine an element. The intrinsic function allocated() lets you determine if the array is allocated or not.

That said, just about the only thing that your program can do when it tries to do something else to an unallocated array is give up. Exceptions such as available in C# or other languages, allow you to jump to a completely different part of the program, but you cannot repair what went wrong either.

You need to solve the bug.

0 Kudos
Ibrahim_K_
New Contributor I
2,547 Views

I am attaching my notes in two replies. Good luck.

 

0 Kudos
Ibrahim_K_
New Contributor I
2,546 Views

Second note.

 

0 Kudos
Ibrahim_A_
Novice
2,507 Views

@Ibrahim_K_ 

I was able to compile the C++/Fortran codes successfully for matrix multiplication and I added try-catch blocks in the C++ code. I'm still unable to figure out how to send the exception messages to C++ from fortran. For example, how can I pass an exception that there's a number being divided by zero or uninitiated variable?

The fortran code can detect them using Run-time error detection, but the fortran code stops working once these issues are detected without going back to the C++ code.

Thanks

0 Kudos
Steve_Lionel
Honored Contributor III
2,505 Views

See if SIGNALQQ does anything for you.

0 Kudos
Ibrahim_A_
Novice
2,430 Views

@Steve_Lionel 

Are there any sample codes of using SIGNALQQ and GETEXCEPTIONPTRSQQ? I was trying to find them in the documentation but I couldn't find them.

0 Kudos
Steve_Lionel
Honored Contributor III
2,422 Views

Oh,. what a merry chase you started me on...

The Intel documentation does have examples of SIGNALQQ and GETEXCEPTIONPTRSQQ. The examples don't work, the documentation is incomplete and has errors. I am sure that none of this has been looked at since the early days of DVF.

The section Using SIGNALQQ is most enlightening, in particular:

SIGNALQQ is just a Fortran jacket to the C run-time signal() function. When you call SIGNALQQ, you are actually registering your signal handler (or action) for a particular signal with the C run-time system. The C run-time system simply stores your handler (or action) in an internal exception action table or variable where it associates your handler with the desired signal. The operating system has no knowledge of this association.

As I wrote earlier, you can use SIGNALQQ to establish a handler for processor-detected errors such as floating point errors, but you can do that in C/C++ as well. 

I am kicking myself, though, because I completely forgot about ESTABLISHQQ even though I am the one who designed it! This gives you a hook into both processor errors AND Fortran run-time library errors. What it doesn't do, though, is connect to C's SEH. Still, it may do something for you.

I have attached a working program, based on the manual's example, demonstrating SIGNALQQ and GETEXCEPTIONPTRSQQ. You must compile this with /fpe:0 or else you won't get the zerodivide. Do note that handling the zerodivide causes it to be retried, hence the STOP. This conflicts with the documentation and I am a bit puzzled by it (though it is reminiscent of VAX behavior on FP "faults".) One amusing thing is that the handler is a function that returns a value, but the documentation never describes this value and a C signal handler is a subroutine (void), no return value.

I will get around to submitting a ticket to Intel to see if they can correct the SIGNALQQ/GETEXCEPTIONPTRSQQ documentation and examples.

0 Kudos
Ibrahim_A_
Novice
2,399 Views

@Steve_Lionel 

Thanks you. The code is working fine without using a C++ caller. The caller is the main program. I decided to do that as a start. I tried to replace the STOP by RETURN because I wanted the code to return to the main program after calling GETEXCEPTIONPTRSQQ. Is that possible?

0 Kudos
Steve_Lionel
Honored Contributor III
2,396 Views

As far as I know, that is not possible. 

Fortran does have a set of features (the intrinsic modules IEEE_ARITHMETIC, IEEE_EXCEPTIONS, IEEE_FEATURES)that give you the ability to detect that a FP operation has failed and take action, but this isn't "exception handling". It also requires you to compile with /fp:strict. If you have a small set of operations that could be problematic, you could use the IEEE modules to deal with it, but it might be easier to just pretest the inputs before the operations.

0 Kudos
Ibrahim_A_
Novice
2,354 Views

@Steve_Lionel 

I see. Can other exceptions such as uninitialized variable be trapped within fortran and the program exits gracefully?

0 Kudos
Steve_Lionel
Honored Contributor III
2,339 Views

Yes. See attached example.

D:\Projects>ifort /check t.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 19.1.2.254 Build 20200623
Copyright (C) 1985-2020 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 14.27.29111.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:t.exe
-subsystem:console
t.obj

D:\Projects>t.exe
 Exiting due to
 forrtl: severe (194): Run-Time Check Failure. The variable \'TEST$N\' is being
 used in \'D:\Projects\t.f90(11,1)\' without being defined
0 Kudos
Reply