0

I used 'ctypes' library to call Fortran code in python. Here, the zd.f90 is packaged as a dynamic link library (zd.so). This DLL can run by using Fortran code, and I meet some problem when I call this DLL in python.

main.f90 of Fortran code

program main
  use ZD1
  implicit none
  call ZD()
  write(*,'(/,A,$)') 'PRESS ENTER TO EXIT ...'
  read(*,*)
end program main

zd.f90 of Fortran module code

module ZD1
  implicit none
  public
  integer, parameter :: species_max = 3,  species_length = 4
  double precision                          :: density(species_max)
  character(species_length)                 :: species_name(species_max)
  data species_name(1:species_max) &
  /"E   ","AR  ","AR^+"/
contains
subroutine ZD()
  implicit none
  integer :: i
  do i = 1, species_max
  density(i) = 1.0d0 +i
  enddo

  do i = 1, species_max
    write(*,'(3(1x,A16))') species_name(i)
  enddo

  do i = 1, species_max
    write(*,'(3(1X,F5.2))') density(i)
  enddo

end subroutine ZD
end module ZD1

test.py

import ctypes as cty
zd = cty.CDLL('/mnt/e/test/zd.so')

zd.__zd1_MOD_zd()
print(zd.__zd1_MOD_density)
print(zd.__zd1_MOD_species_name)
print('PRESS ENTER TO EXIT ...')

# output
             E
             AR
             AR^+
  2.00
  3.00
  4.00
<_FuncPtr object at 0x7fad40202b00>
<_FuncPtr object at 0x7fad40202bc0>
PRESS ENTER TO EXIT ...

The zd.__zd1_MOD_zd() can run sucessfully. But, I cant get data in density and species_name var of Fortran by python. Here is my attempt.

>>>import ctypes as cty
>>>zd = cty.CDLL('/mnt/e/test/zd.so')

>>>zd.__zdplaskin_MOD_species_name
      This command does not have any output

>>>print(zd.__zdplaskin_MOD_species_name)
     ouput:<_FuncPtr object at 0x7f956c82dd80>

>>>print(dir(zd.__zdplaskin_MOD_species_name))
    ouput:['__bool__', '__call__', '__class__', '__ctypes_from_outparam__', '__delattr__',
 '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
 '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', 
'__name__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', 
'__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_b_base_', 
'_b_needsfree_', '_flags_', '_objects', '_restype_', 'argtypes', 'errcheck', 'restype']

>>>print(zd.__zdplaskin_MOD_species_name.__ctypes_from_outparam__)
    ouput:<built-in method __ctypes_from_outparam__ of _FuncPtr object at 0x7fba9fe39d80>

>>>print(zd.__zdplaskin_MOD_species_name.__name__)
    ouput:__zd1_MOD_species_name

>>>print(zd.__zdplaskin_MOD_species_name.__str__)
    ouput:<method-wrapper '__str__' of _FuncPtr object at 0x7fe956269d80>
>>>print(zd.__zd1_MOD_species_name.value)
    ouput:AttributeError: '_FuncPtr' object has no attribute 'value'

And I use nm -D zd.so > list.txtcommand, I found that the types of density and species_name var is B and D in zd.so. Here is output. I hope this can help everyone right. Thank you very much and I use Python 3.10.6 in ubuntu 18.04.

                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
000000000020104c B __bss_start
                 w __cxa_finalize
                 w __gmon_start__
0000000000201060 B __zd1_MOD_density
0000000000201040 D __zd1_MOD_species_name
00000000000007da T __zd1_MOD_zd
000000000020104c D _edata
0000000000201078 B _end
000000000000099c T _fini
                 U _gfortran_st_write
                 U _gfortran_st_write_done
                 U _gfortran_transfer_character_write
                 U _gfortran_transfer_real_write
0000000000000688 T _init
YOU
  • 29
  • 3
  • 1
    You should show how those functions look like in the Fortran code. – Vladimir F Героям слава Dec 01 '22 at 05:28
  • `print(zd.__zdplaskin_MOD_species_name.__name_)`: typo **`__name__`** (missing a trailing ***\_***). That is a function, so you should **call** it: `zd.__zdplaskin_MOD_species_name()`. But read [\[SO\]: C function called from Python via ctypes returns incorrect value (@CristiFati's answer)](https://stackoverflow.com/a/58611011/4788546) first. You should know functions signatures. – CristiFati Dec 02 '22 at 23:04
  • thank, I have listed my fortran code. And I try use 'zd.__zdplaskin_MOD_species_name()'. It shown as 'Segmentation fault'. – YOU Dec 05 '22 at 02:37
  • I sorry about this. I have corrected my question and thank you for your guidance! – YOU Dec 06 '22 at 02:50
  • Python and Fortran cannot share variables because they are structured completely differently internally. Easiest way is to create routines to return the values. Note that the 2D array in Fortran is contiguous so get it as one string and then break it up on the python side. – cup Dec 28 '22 at 08:49

0 Answers0