f2py icon indicating copy to clipboard operation
f2py copied to clipboard

Using user defined type

Open eogbe opened this issue 6 years ago • 12 comments

Hi

I am trying to generate a wrapper for my f90 code using f2py. It works for common types like int, real, etc but when i have user defined type I get the following error:

running build running config_cc unifing config_cc, config, build_clib, build_ext, build commands --compiler options running config_fc unifing config_fc, config, build_clib, build_ext, build commands --fcompiler options running build_src build_src building extension "mc79reorder" sources creating /tmp/tmpDnh_3K/src.linux-x86_64-2.7 f2py options: [] f2py: mc79sign.pyf Reading fortran codes... Reading file 'mc79sign.pyf' (format:free) Post-processing... Block: mc79reorder Block: hsl_mc79_integer Block: unknown_type Block: mc79_matching Post-processing (stage 2)... Block: mc79reorder Block: unknown_interface Block: hsl_mc79_integer Block: unknown_type Block: mc79_matching Building modules... Building module "mc79reorder"... Constructing F90 module support for "hsl_mc79_integer"... Skipping type unknown_type Creating wrapper for Fortran subroutine "mc79_matching"("mc79_matching")... Constructing wrapper function "hsl_mc79_integer.mc79_matching"... getctype: "integer(kind=myint_mc79)" is mapped to C "int" (to override define dict(integer = dict(myint_mc79="<C typespec>")) in /home/eogbe/Documents/solvers/hslcodes/hsl_mc79-1.1.0/src/test/newtest/.f2py_f2cmap file). getctype: "integer(kind=myint_mc79)" is mapped to C "int" (to override define dict(integer = dict(myint_mc79="<C typespec>")) in /home/eogbe/Documents/solvers/hslcodes/hsl_mc79-1.1.0/src/test/newtest/.f2py_f2cmap file). getctype: "integer(kind=myint_mc79)" is mapped to C "int" (to override define dict(integer = dict(myint_mc79="<C typespec>")) in /home/eogbe/Documents/solvers/hslcodes/hsl_mc79-1.1.0/src/test/newtest/.f2py_f2cmap file). getctype: "integer(kind=myint_mc79)" is mapped to C "int" (to override define dict(integer = dict(myint_mc79="<C typespec>")) in /home/eogbe/Documents/solvers/hslcodes/hsl_mc79-1.1.0/src/test/newtest/.f2py_f2cmap file). getctype: "integer(kind=myint_mc79)" is mapped to C "int" (to override define dict(integer = dict(myint_mc79="<C typespec>")) in /home/eogbe/Documents/solvers/hslcodes/hsl_mc79-1.1.0/src/test/newtest/.f2py_f2cmap file). getctype: "integer(kind=myint_mc79)" is mapped to C "int" (to override define dict(integer = dict(myint_mc79="<C typespec>")) in /home/eogbe/Documents/solvers/hslcodes/hsl_mc79-1.1.0/src/test/newtest/.f2py_f2cmap file). getctype: No C-type found in "{'attrspec': [], 'typename': 'mc79_control', 'intent': ['in'], 'typespec': 'type'}", assuming void. getctype: "integer(kind=myint_mc79)" is mapped to C "int" (to override define dict(integer = dict(myint_mc79="<C typespec>")) in /home/eogbe/Documents/solvers/hslcodes/hsl_mc79-1.1.0/src/test/newtest/.f2py_f2cmap file). getctype: "integer(kind=myint_mc79)" is mapped to C "int" (to override define dict(integer = dict(myint_mc79="<C typespec>")) in /home/eogbe/Documents/solvers/hslcodes/hsl_mc79-1.1.0/src/test/newtest/.f2py_f2cmap file). getctype: "integer(kind=myint_mc79)" is mapped to C "int" (to override define dict(integer = dict(myint_mc79="<C typespec>")) in /home/eogbe/Documents/solvers/hslcodes/hsl_mc79-1.1.0/src/test/newtest/.f2py_f2cmap file). getctype: "integer(kind=myint_mc79)" is mapped to C "int" (to override define dict(integer = dict(myint_mc79="<C typespec>")) in /home/eogbe/Documents/solvers/hslcodes/hsl_mc79-1.1.0/src/test/newtest/.f2py_f2cmap file). getctype: "integer(kind=myint_mc79)" is mapped to C "int" (to override define dict(integer = dict(myint_mc79="<C typespec>")) in /home/eogbe/Documents/solvers/hslcodes/hsl_mc79-1.1.0/src/test/newtest/.f2py_f2cmap file). getctype: "integer(kind=myint_mc79)" is mapped to C "int" (to override define dict(integer = dict(myint_mc79="<C typespec>")) in /home/eogbe/Documents/solvers/hslcodes/hsl_mc79-1.1.0/src/test/newtest/.f2py_f2cmap file). getctype: "integer(kind=myint_mc79)" is mapped to C "int" (to override define dict(integer = dict(myint_mc79="<C typespec>")) in /home/eogbe/Documents/solvers/hslcodes/hsl_mc79-1.1.0/src/test/newtest/.f2py_f2cmap file). getctype: "integer(kind=myint_mc79)" is mapped to C "int" (to override define dict(integer = dict(myint_mc79="<C typespec>")) in /home/eogbe/Documents/solvers/hslcodes/hsl_mc79-1.1.0/src/test/newtest/.f2py_f2cmap file). getctype: "integer(kind=myint_mc79)" is mapped to C "int" (to override define dict(integer = dict(myint_mc79="<C typespec>")) in /home/eogbe/Documents/solvers/hslcodes/hsl_mc79-1.1.0/src/test/newtest/.f2py_f2cmap file). getctype: "integer(kind=myint_mc79)" is mapped to C "int" (to override define dict(integer = dict(myint_mc79="<C typespec>")) in /home/eogbe/Documents/solvers/hslcodes/hsl_mc79-1.1.0/src/test/newtest/.f2py_f2cmap file). getctype: "integer(kind=myint_mc79)" is mapped to C "int" (to override define dict(integer = dict(myint_mc79="<C typespec>")) in /home/eogbe/Documents/solvers/hslcodes/hsl_mc79-1.1.0/src/test/newtest/.f2py_f2cmap file). getctype: "integer(kind=myint_mc79)" is mapped to C "int" (to override define dict(integer = dict(myint_mc79="<C typespec>")) in /home/eogbe/Documents/solvers/hslcodes/hsl_mc79-1.1.0/src/test/newtest/.f2py_f2cmap file). getctype: No C-type found in "{'attrspec': [], 'typename': 'mc79_control', 'intent': ['in'], 'typespec': 'type'}", assuming void. getctype: No C-type found in "{'attrspec': [], 'typename': 'mc79_control', 'intent': ['in'], 'typespec': 'type'}", assuming void. Traceback (most recent call last): File "/home/eogbe/anaconda2/bin/f2py", line 28, in main() File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/f2py/f2py2e.py", line 648, in main run_compile() File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/f2py/f2py2e.py", line 633, in run_compile setup(ext_modules=[ext]) File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/distutils/core.py", line 169, in setup return old_setup(**new_attr) File "/home/eogbe/anaconda2/lib/python2.7/distutils/core.py", line 151, in setup dist.run_commands() File "/home/eogbe/anaconda2/lib/python2.7/distutils/dist.py", line 953, in run_commands self.run_command(cmd) File "/home/eogbe/anaconda2/lib/python2.7/distutils/dist.py", line 972, in run_command cmd_obj.run() File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/distutils/command/build.py", line 47, in run old_build.run(self) File "/home/eogbe/anaconda2/lib/python2.7/distutils/command/build.py", line 127, in run self.run_command(cmd_name) File "/home/eogbe/anaconda2/lib/python2.7/distutils/cmd.py", line 326, in run_command self.distribution.run_command(command) File "/home/eogbe/anaconda2/lib/python2.7/distutils/dist.py", line 972, in run_command cmd_obj.run() File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/distutils/command/build_src.py", line 148, in run self.build_sources() File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/distutils/command/build_src.py", line 165, in build_sources self.build_extension_sources(ext) File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/distutils/command/build_src.py", line 327, in build_extension_sources sources = self.f2py_sources(sources, ext) File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/distutils/command/build_src.py", line 544, in f2py_sources + ['--build-dir', target_dir, source]) File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/f2py/f2py2e.py", line 440, in run_main ret = buildmodules(postlist) File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/f2py/f2py2e.py", line 384, in buildmodules dict_append(ret[mnames[i]], rules.buildmodule(modules[i], um)) File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/f2py/rules.py", line 1211, in buildmodule mr, wrap = f90mod_rules.buildhooks(m) File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/f2py/f90mod_rules.py", line 202, in buildhooks api, wrap = rules.buildapi(b) File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/f2py/rules.py", line 1368, in buildapi vrd = capi_maps.sign2map(a, var[a]) File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/f2py/capi_maps.py", line 603, in sign2map ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, var) File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/f2py/capi_maps.py", line 412, in getpydocsign sig = '%s : %s %s%s' % (a, opt, c2py_map[ctype], init) KeyError: 'void'

Is there any work around derived data types? I 'm using f2py with gfortran and python 2.7 on centOS. Emmanuel

eogbe avatar Nov 22 '18 17:11 eogbe

The solution is provided in https://sysbio.ioc.ee/projects/f2py2e/FAQ.html#q-what-if-fortran-90-code-uses-type-spec-kind-kind

pearu avatar Nov 22 '18 17:11 pearu

Maybe we could catch the KeyError and provide a more helpful error message?

mattip avatar Nov 22 '18 17:11 mattip

@pearu Could you please elaborate using the sample I have below?

MODULE example
  IMPLICIT NONE
  PRIVATE

! --------------------------------------------------- ! Derived type definitions ! --------------------------------------------------- TYPE, PUBLIC :: userdefined INTEGER :: lp = 6
INTEGER :: mp = 6 END TYPE mc79_control

  PUBLIC hsl
CONTAINS

  SUBROUTINE hsl(m,n,ptr,row,rowmatch,colmatch,control)
    INTEGER (userdefined), INTENT (IN) :: m
    INTEGER (userdefined), INTENT (IN) :: n
    INTEGER (userdefined), INTENT (IN) :: ptr(n+1)
    INTEGER (userdefined), INTENT (IN) :: row(:)
    INTEGER (userdefined), INTENT (OUT) :: rowmatch(m)
    INTEGER (userdefined), INTENT (OUT) :: colmatch(n)
    TYPE (userdefined), INTENT (IN) :: control
    lp = control%lp
    mp = control%mp
  END SUBROUTINE hsl
END MODULE example

How do I generate the fortran to c map for this? Emmanuel

eogbe avatar Nov 22 '18 17:11 eogbe

Try create a file /home/eogbe/Documents/solvers/hslcodes/hsl_mc79-1.1.0/src/test/newtest/.f2py_f2cmap with the following content: {'integer':{'userdefined':'int'}}

Btw, shouldn't END TYPE mc79_control be END TYPE userdefined ?

pearu avatar Nov 22 '18 18:11 pearu

Yes my bad. It is "end userdefined" in my code.

How do i call the code after creating .f2py_f2cmap? f2py -m mc79reorder -h hsl_79.pyf example.f90 .f2py_f2cmap didn't seem to work.

eogbe avatar Nov 22 '18 18:11 eogbe

I used message

getctype: "integer(kind=myint_mc79)" is mapped to C "int" (to override define dict(integer = dict(myint_mc79="")) in /home/eogbe/Documents/solvers/hslcodes/hsl_mc79-1.1.0/src/test/newtest/.f2py_f2cmap file).

as a hint for the proper .f2py_f2cmap location.

When you created the .f2py_f2cmap, were there any effect? Were there any changes in error messages, for instance?

("Does not seem to work" is not really useful for giving useful feedback.)

pearu avatar Nov 22 '18 18:11 pearu

Running f2py -m mc79reorder -h hsl_79.pyf example.f90 .f2py_f2cmap I get the output:

Reading .f2py_f2cmap ... Mapping "integer(kind=userdefined)" to "int" Successfully applied user defined changes from .f2py_f2cmap Reading fortran codes... Reading file 'example.f90' (format:free) Line #9 in example.f90:" TYPE, PUBLIC :: userdefined" analyzeline: No name/args pattern found for line. Reading file '.f2py_f2cmap' (format:free) Post-processing... Block: mc79reorder Block: example Block: unknown_type Block: hsl Post-processing (stage 2)... Block: mc79reorder Block: unknown_interface Block: example Block: unknown_type Block: hsl Saving signatures to file "./hsl_79.pyf" {'attrspec': ['private', 'public']} In: :mc79reorder:example.f90:example vars2fortran: No typespec for argument "hsl".

It successfully applies the user defined changes but still reports "no typespec" for "hsl" When i tried to create the .so file with the command "f2py -c --fcompiler=gnu95 hsl_79.pyf example.f90 .f2py_f2cmap" i get the "getctype: no c type found " error as before (without using .f2py_f2cmap):

Reading .f2py_f2cmap ... Mapping "integer(kind=userdefined)" to "int" Successfully applied user defined changes from .f2py_f2cmap running build running config_cc unifing config_cc, config, build_clib, build_ext, build commands --compiler options running config_fc unifing config_fc, config, build_clib, build_ext, build commands --fcompiler options running build_src build_src building extension "mc79reorder" sources creating /tmp/tmpTCBdVF/src.linux-x86_64-2.7 f2py options: [] f2py: hsl_79.pyf Reading fortran codes... Reading file 'hsl_79.pyf' (format:free) Post-processing... Block: mc79reorder Block: example Block: unknown_type Block: hsl Post-processing (stage 2)... Block: mc79reorder Block: unknown_interface Block: example Block: unknown_type Block: hsl Building modules... Building module "mc79reorder"... Constructing F90 module support for "example"... Skipping type unknown_type Creating wrapper for Fortran subroutine "hsl"("hsl")... Constructing wrapper function "example.hsl"... getctype: No C-type found in "{'attrspec': [], 'typename': 'userdefined', 'intent': ['in'], 'typespec': 'type'}", assuming void. getctype: No C-type found in "{'attrspec': [], 'typename': 'userdefined', 'intent': ['in'], 'typespec': 'type'}", assuming void. getctype: No C-type found in "{'attrspec': [], 'typename': 'userdefined', 'intent': ['in'], 'typespec': 'type'}", assuming void. Traceback (most recent call last): File "/home/eogbe/anaconda2/bin/f2py", line 28, in main() File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/f2py/f2py2e.py", line 648, in main run_compile() File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/f2py/f2py2e.py", line 633, in run_compile setup(ext_modules=[ext]) File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/distutils/core.py", line 169, in setup return old_setup(**new_attr) File "/home/eogbe/anaconda2/lib/python2.7/distutils/core.py", line 151, in setup dist.run_commands() File "/home/eogbe/anaconda2/lib/python2.7/distutils/dist.py", line 953, in run_commands self.run_command(cmd) File "/home/eogbe/anaconda2/lib/python2.7/distutils/dist.py", line 972, in run_command cmd_obj.run() File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/distutils/command/build.py", line 47, in run old_build.run(self) File "/home/eogbe/anaconda2/lib/python2.7/distutils/command/build.py", line 127, in run self.run_command(cmd_name) File "/home/eogbe/anaconda2/lib/python2.7/distutils/cmd.py", line 326, in run_command self.distribution.run_command(command) File "/home/eogbe/anaconda2/lib/python2.7/distutils/dist.py", line 972, in run_command cmd_obj.run() File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/distutils/command/build_src.py", line 148, in run self.build_sources() File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/distutils/command/build_src.py", line 165, in build_sources self.build_extension_sources(ext) File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/distutils/command/build_src.py", line 327, in build_extension_sources sources = self.f2py_sources(sources, ext) File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/distutils/command/build_src.py", line 544, in f2py_sources + ['--build-dir', target_dir, source]) File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/f2py/f2py2e.py", line 440, in run_main ret = buildmodules(postlist) File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/f2py/f2py2e.py", line 384, in buildmodules dict_append(ret[mnames[i]], rules.buildmodule(modules[i], um)) File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/f2py/rules.py", line 1211, in buildmodule mr, wrap = f90mod_rules.buildhooks(m) File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/f2py/f90mod_rules.py", line 202, in buildhooks api, wrap = rules.buildapi(b) File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/f2py/rules.py", line 1368, in buildapi vrd = capi_maps.sign2map(a, var[a]) File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/f2py/capi_maps.py", line 603, in sign2map ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, var) File "/home/eogbe/anaconda2/lib/python2.7/site-packages/numpy/f2py/capi_maps.py", line 412, in getpydocsign sig = '%s : %s %s%s' % (a, opt, c2py_map[ctype], init) KeyError: 'void'

There is something i am doing wrong i think.

eogbe avatar Nov 22 '18 19:11 eogbe

The problems is in argument control:

TYPE (userdefined), INTENT (IN) :: control

f2py currently does not support wrapping functions with derived type arguments.

pearu avatar Nov 22 '18 19:11 pearu

That's what i initially thought. I was thinking there was a way around it or any suggestions to help me accomplish my task.

Thanks, Emmanuel

eogbe avatar Nov 22 '18 19:11 eogbe

The solution is provided in https://sysbio.ioc.ee/projects/f2py2e/FAQ.html#q-what-if-fortran-90-code-uses-type-spec-kind-kind

This link is dead.

lamorton avatar Jan 06 '21 20:01 lamorton

The relevant piece of documentation can be found in github history, for instance: https://github.com/numpy/numpy/blob/a859492c7b07dac0a56d9a08d6739e006a528f87/numpy/f2py/docs/FAQ.txt#L258

pearu avatar Jan 06 '21 20:01 pearu

@pearu Could you please elaborate using the sample I have below? `module example implicit none

!---------------------------------- ! type define !----------------------------------

type array_car
    integer :: N1, N2, N3
    complex(kind=8), allocatable :: c_1d(:)
    real(kind=8), allocatable :: r_1d(:)
    integer,allocatable :: i_1d(:)
end type array_car

subroutine construct_qlist(e) implicit none type(array_car) :: out real(kind=8) :: t(3,3),tt(3,3), q1(3), q2(3) end subroutine hsl end module example `

cuijie-nano avatar Mar 08 '24 14:03 cuijie-nano