Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
New Contributor I
38 Views

Tracebacks in DLLs called from Python

Consider the following Fortran code (compiled into a DLL):

module test

contains
    
    subroutine dll_test() bind (c, name='dll_test')
!DEC$ ATTRIBUTES DLLEXPORT :: dll_test
    call crash()
    end subroutine dll_test
    
    subroutine crash()
    integer :: j
    integer,dimension(:),allocatable :: k 
    j = k(1)
    end subroutine crash

end module test

I'm trying to compile a debug DLL with traceback info, so I'm using: /traceback /check:all /debug:full /Od

Now, I want to load this DLL from Python. Like so:

import ctypes

lib = ctypes.cdll.LoadLibrary('dll_test.dll')

lib.dll_test()

As expected, it throws a runtime error, but without a useful traceback:

forrtl: severe (408): fort: (8): Attempt to fetch from allocatable variable K when it is not allocated

Image              PC                Routine            Line        Source
libifcoremdd.dll   00007FF876B853B7  Unknown               Unknown  Unknown
dll_test.dll       00007FF89B201547  Unknown               Unknown  Unknown
dll_test.dll       00007FF89B20146B  Unknown               Unknown  Unknown
_ctypes.pyd        00007FF899221B23  Unknown               Unknown  Unknown
_ctypes.pyd        00007FF8992201F3  Unknown               Unknown  Unknown
_ctypes.pyd        00007FF89921B773  Unknown               Unknown  Unknown
_ctypes.pyd        00007FF89921C2C9  Unknown               Unknown  Unknown
_ctypes.pyd        00007FF899216F6A  Unknown               Unknown  Unknown
python37.dll       00007FF85DD0674A  Unknown               Unknown  Unknown
python37.dll       00007FF85DD0E845  Unknown               Unknown  Unknown
python37.dll       00007FF85DD0F21E  Unknown               Unknown  Unknown
python37.dll       00007FF85DCFF188  Unknown               Unknown  Unknown
python37.dll       00007FF85DCE4963  Unknown               Unknown  Unknown
python37.dll       00007FF85DCE48C1  Unknown               Unknown  Unknown
python37.dll       00007FF85DCE486B  Unknown               Unknown  Unknown
python37.dll       00007FF85DE97541  Unknown               Unknown  Unknown
python37.dll       00007FF85DE97D70  Unknown               Unknown  Unknown
python37.dll       00007FF85DE9740F  Unknown               Unknown  Unknown
python37.dll       00007FF85DDDD4D7  Unknown               Unknown  Unknown
python37.dll       00007FF85DDDD582  Unknown               Unknown  Unknown
python37.dll       00007FF85DD72776  Unknown               Unknown  Unknown
python37.dll       00007FF85DD1166A  Unknown               Unknown  Unknown
python37.dll       00007FF85DD112B4  Unknown               Unknown  Unknown
python.exe         00007FF746401260  Unknown               Unknown  Unknown
KERNEL32.DLL       00007FF8B82F2784  Unknown               Unknown  Unknown
ntdll.dll          00007FF8B9040C51  Unknown               Unknown  Unknown

 

However, if I modify the code so that the two routines are not in a module (just comment out the first two and last line), then I do get a traceback:

forrtl: severe (408): fort: (8): Attempt to fetch from allocatable variable K when it is not allocated

Image              PC                Routine            Line        Source
libifcoremdd.dll   00007FF876B853B7  Unknown               Unknown  Unknown
dll_test.dll       00007FF8932914F6  CRASH                      30  dll_test.f90
dll_test.dll       00007FF89329141A  CRASH                      14  dll_test.f90
_ctypes.pyd        00007FF899221B23  Unknown               Unknown  Unknown
_ctypes.pyd        00007FF8992201F3  Unknown               Unknown  Unknown
_ctypes.pyd        00007FF89921B773  Unknown               Unknown  Unknown
_ctypes.pyd        00007FF89921C2C9  Unknown               Unknown  Unknown
_ctypes.pyd        00007FF899216F6A  Unknown               Unknown  Unknown
python37.dll       00007FF85DD0674A  Unknown               Unknown  Unknown
python37.dll       00007FF85DD0E845  Unknown               Unknown  Unknown
python37.dll       00007FF85DD0F21E  Unknown               Unknown  Unknown
python37.dll       00007FF85DCFF188  Unknown               Unknown  Unknown
python37.dll       00007FF85DCE4963  Unknown               Unknown  Unknown
python37.dll       00007FF85DCE48C1  Unknown               Unknown  Unknown
python37.dll       00007FF85DCE486B  Unknown               Unknown  Unknown
python37.dll       00007FF85DE97541  Unknown               Unknown  Unknown
python37.dll       00007FF85DE97D70  Unknown               Unknown  Unknown
python37.dll       00007FF85DE9740F  Unknown               Unknown  Unknown
python37.dll       00007FF85DDDD4D7  Unknown               Unknown  Unknown
python37.dll       00007FF85DDDD582  Unknown               Unknown  Unknown
python37.dll       00007FF85DD72776  Unknown               Unknown  Unknown
python37.dll       00007FF85DD1166A  Unknown               Unknown  Unknown
python37.dll       00007FF85DD112B4  Unknown               Unknown  Unknown
python.exe         00007FF746401260  Unknown               Unknown  Unknown
KERNEL32.DLL       00007FF8B82F2784  Unknown               Unknown  Unknown
ntdll.dll          00007FF8B9040C51  Unknown               Unknown  Unknown

So, how can I get a traceback and still use modules? I've tried various settings but can't get anything to work. Is this some kind of flaw in the Intel compiler?

Any help is appreciated!

 

0 Kudos
5 Replies
Highlighted
New Contributor I
38 Views

Forgot to mention: Windows 10, 64 bit, Python 3.7.

0 Kudos
Highlighted
Valued Contributor III
38 Views

Looks like a question for Intel support: submit a request at https://supporttickets.intel.com/?lang=en-US

0 Kudos
Highlighted
New Contributor I
38 Views

It looks like incremental linking may have been the problem (or one of them). Setting /INCREMENTAL:NO makes this test case work. (I was already doing this but I didn't notice that CMake was adding /INCREMENTAL back and that was taking precedence).

Follow up question: should I be calling for_rtl_init_ when using a Fortran DLL from Python? The documentation says to do this when the main program is C.

0 Kudos
Highlighted
Valued Contributor III
38 Views

Jacob Williams wrote:

.. The documentation says to do this when the main program is C.

Again, you may want to cross-check with Intel support to get the "best" answer.

I'm of the impression you don't need to invoke for_rtl_* procedures, especially if your Fortran DLL code is pretty much 'standard' Fortran.  And the 'classes' exported from the Fortran DLLs follow, in principle, the RAII (resource allocation is initialization) and DIRR (destruction is resource release) approaches to software solutions and the library code does all the common sense stuff pertaining to Fortran dynamic allocation, IO, etc.

0 Kudos
Highlighted
Black Belt Retired Employee
38 Views

I've never found it necessary to call for_rtl_init_ on Windows for any reason. The spelling of the name is a big hint that it is for Linux and MacOS only, though the documentation doesn't say that explicitly. I'll note that Windows provides DLLs with the ability to initialize themselves, something the other OSes don't.

--
Steve (aka "Doctor Fortran") - https://stevelionel.com/drfortran
0 Kudos