Hello, I have a problem with a generic interface and C binding, as
demonstrated in a following program. I am receiving compile time error in
the second call. As I understand it, it is because of the assumed size
array. Is there any way to fix it? (At least because of theoretical
reasons, I can live without the generic interface.)
Vladimir
"ge.f90", Line = 37, Column = 6: ERROR: Incorrect argument rank in generic
procedure call "FFTW_PLAN_GEN"
or
Error: There is no specific function for the generic 'fftw_plan_gen' at (1)
program test
use iso_c_binding
implicit none
integer, parameter :: C_FFTW_R2R_KIND = C_INT32_T
interface fftw_plan_gen
type(C_PTR) function fftw_plan_r2r_1d(n,in,out,kind,flags) bind(C,
name='fftw_plan_r2r_1d')
import
integer(C_INT), value :: n
real(C_DOUBLE), dimension(*), intent(out) :: in
real(C_DOUBLE), dimension(*), intent(out) :: out
integer(C_FFTW_R2R_KIND), value :: kind
integer(C_INT), value :: flags
end function fftw_plan_r2r_1d
type(C_PTR) function fftw_plan_r2r_2d(n0,n1,in,out,kind0,kind1,flags)
bind(C, name='fftw_plan_r2r_2d')
import
integer(C_INT), value :: n0
integer(C_INT), value :: n1
real(C_DOUBLE), dimension(*), intent(out) :: in
real(C_DOUBLE), dimension(*), intent(out) :: out
integer(C_FFTW_R2R_KIND), value :: kind0
integer(C_FFTW_R2R_KIND), value :: kind1
integer(C_INT), value :: flags
end function fftw_plan_r2r_2d
end interface fftw_plan_gen
type(c_ptr) :: p
real(c_double), dimension(1,1) :: a
p= fftw_plan_r2r_2d(1_c_int,1_c_int, a, a, 0_c_int32_t, 0_c_int32_t,
0_c_int)
p= fftw_plan_gen(1_c_int,1_c_int, a, a, 0_c_int32_t, 0_c_int32_t,
0_c_int)
write (*,*) transfer(p,1_c_size_t)
end program test
> Hello, I have a problem with a generic interface and C binding, as
> demonstrated in a following program. I am receiving compile time error
> in the second call. As I understand it, it is because of the assumed
> size array. Is there any way to fix it? (At least because of theoretical
> reasons, I can live without the generic interface.)
> Vladimir
> "ge.f90", Line = 37, Column = 6: ERROR: Incorrect argument rank in
> generic procedure call "FFTW_PLAN_GEN"
> or
> Error: There is no specific function for the generic 'fftw_plan_gen' at
> (1)
> program test
> use iso_c_binding
> implicit none
> interface fftw_plan_gen
> type(C_PTR) function fftw_plan_r2r_1d(n,in,out,kind,flags) bind(C,
> name='fftw_plan_r2r_1d')
> import
> integer(C_INT), value :: n
> real(C_DOUBLE), dimension(*), intent(out) :: in
> real(C_DOUBLE), dimension(*), intent(out) :: out
> integer(C_FFTW_R2R_KIND), value :: kind
> integer(C_INT), value :: flags
> end function fftw_plan_r2r_1d
> type(C_PTR) function
> fftw_plan_r2r_2d(n0,n1,in,out,kind0,kind1,flags) bind(C,
> name='fftw_plan_r2r_2d')
> import
> integer(C_INT), value :: n0
> integer(C_INT), value :: n1
> real(C_DOUBLE), dimension(*), intent(out) :: in
> real(C_DOUBLE), dimension(*), intent(out) :: out
> integer(C_FFTW_R2R_KIND), value :: kind0
> integer(C_FFTW_R2R_KIND), value :: kind1
> integer(C_INT), value :: flags
> end function fftw_plan_r2r_2d
> end interface fftw_plan_gen
> type(c_ptr) :: p
> real(c_double), dimension(1,1) :: a
> p= fftw_plan_r2r_2d(1_c_int,1_c_int, a, a, 0_c_int32_t, 0_c_int32_t,
> 0_c_int)
> p= fftw_plan_gen(1_c_int,1_c_int, a, a, 0_c_int32_t, 0_c_int32_t,
> 0_c_int)
> write (*,*) transfer(p,1_c_size_t)
> end program test
\"Vladimír Fuka <\"name.surname at <mffDOTcuniDOTcz">> wrote:
> Hello, I have a problem with a generic interface and C binding, as
> demonstrated in a following program. I am receiving compile time error in
> the second call. As I understand it, it is because of the assumed size
> array. Is there any way to fix it? (At least because of theoretical
> reasons, I can live without the generic interface.)
Assumes size array should be fine.
> "ge.f90", Line = 37, Column = 6: ERROR: Incorrect argument rank in generic
> procedure call "FFTW_PLAN_GEN"
(snip)
> Error: There is no specific function for the generic 'fftw_plan_gen' at (1)
(snip)
> interface fftw_plan_gen
(snip of 1D case)
> type(C_PTR) function fftw_plan_r2r_2d(n0,n1,in,out,kind0,kind1,flags)
> bind(C, name='fftw_plan_r2r_2d')
> import
> integer(C_INT), value :: n0
> integer(C_INT), value :: n1
> real(C_DOUBLE), dimension(*), intent(out) :: in
> real(C_DOUBLE), dimension(*), intent(out) :: out
> integer(C_FFTW_R2R_KIND), value :: kind0
> integer(C_FFTW_R2R_KIND), value :: kind1
> integer(C_INT), value :: flags
> end function fftw_plan_r2r_2d
> end interface fftw_plan_gen
> type(c_ptr) :: p
> real(c_double), dimension(1,1) :: a
Yes, the 2D array a won't match the dimension(*) array, even
though it is legal for an assumed size array.
Exactly what Fortran does with assumed size isn't so obvious, but the usual implementation passes the address of the first element.
If you instead dimension(1,*) or, as you note later (n0,*), then
it should work.
I am not sure if you can get away with two different ones with
the same name and different rank inside the generic. (In case
you want to allow either 1D or 2D passed to fftw_plan_r2r_2d.)
More likely, though, you can give them different names, but the
same bind(name='name') and it will allow it through.
> p= fftw_plan_r2r_2d(1_c_int,1_c_int, a, a, 0_c_int32_t, 0_c_int32_t,
> 0_c_int)
> p= fftw_plan_gen(1_c_int,1_c_int, a, a, 0_c_int32_t, 0_c_int32_t,
> 0_c_int)
Another possibility is to pass a c_ptr to the function, and put
c_loc(a) for each array argument. That is assuming that you don't
want it to select the generic based on rank.
> Hello, I have a problem with a generic interface and C binding, as
> demonstrated in a following program. I am receiving compile time error
> in the second call. As I understand it, it is because of the assumed
> size array. Is there any way to fix it? (At least because of theoretical
> reasons, I can live without the generic interface.)
> Vladimir
> "ge.f90", Line = 37, Column = 6: ERROR: Incorrect argument rank in
> generic procedure call "FFTW_PLAN_GEN"
> or
> Error: There is no specific function for the generic 'fftw_plan_gen' at (1)
> program test
> use iso_c_binding
> implicit none
> interface fftw_plan_gen
> type(C_PTR) function fftw_plan_r2r_1d(n,in,out,kind,flags) bind(C,
> name='fftw_plan_r2r_1d')
> import
> integer(C_INT), value :: n
> real(C_DOUBLE), dimension(*), intent(out) :: in
> real(C_DOUBLE), dimension(*), intent(out) :: out
> integer(C_FFTW_R2R_KIND), value :: kind
> integer(C_INT), value :: flags
> end function fftw_plan_r2r_1d
> type(C_PTR) function fftw_plan_r2r_2d(n0,n1,in,out,kind0,kind1,flags)
> bind(C, name='fftw_plan_r2r_2d')
> import
> integer(C_INT), value :: n0
> integer(C_INT), value :: n1
> real(C_DOUBLE), dimension(*), intent(out) :: in
> real(C_DOUBLE), dimension(*), intent(out) :: out
> integer(C_FFTW_R2R_KIND), value :: kind0
> integer(C_FFTW_R2R_KIND), value :: kind1
> integer(C_INT), value :: flags
> end function fftw_plan_r2r_2d
> end interface fftw_plan_gen
> type(c_ptr) :: p
> real(c_double), dimension(1,1) :: a
> p= fftw_plan_r2r_2d(1_c_int,1_c_int, a, a, 0_c_int32_t, 0_c_int32_t,
> 0_c_int)
> p= fftw_plan_gen(1_c_int,1_c_int, a, a, 0_c_int32_t, 0_c_int32_t, 0_c_int)
> write (*,*) transfer(p,1_c_size_t)
> end program test
No, I am not making it. I am just adding some generic interfaces to my
program in order to have less preprocessor macros. I include the same
subroutine body for complex and real versions x 3 different dimensions and
x 2 (possibly 3) precisions. Now if I specify the dimension or use other
approach recommended by Glen, that even enables different kinds, the
generic name works without change in all of these.
Vladimir
Dne Thu, 26 Apr 2012 07:48:01 +0200 Paul Anton Letnes
<paul.anton.let...@nospam.gmail.kthxbai.com> napsal(a):
> Are you trying to make Fortran bindings to the FFTW library? Because
> FFTW includes those by default. Or am I missing something?
> Paul
> On 25.04.12 16:03, \"Vladimír Fuka <\"name.surname at >> wrote:
>> Hello, I have a problem with a generic interface and C binding, as
>> demonstrated in a following program. I am receiving compile time error
>> in the second call. As I understand it, it is because of the assumed
>> size array. Is there any way to fix it? (At least because of theoretical
>> reasons, I can live without the generic interface.)
>> Vladimir
>> "ge.f90", Line = 37, Column = 6: ERROR: Incorrect argument rank in
>> generic procedure call "FFTW_PLAN_GEN"
>> or
>> Error: There is no specific function for the generic 'fftw_plan_gen' at
>> (1)
>> program test
>> use iso_c_binding
>> implicit none
>> interface fftw_plan_gen
>> type(C_PTR) function fftw_plan_r2r_1d(n,in,out,kind,flags) bind(C,
>> name='fftw_plan_r2r_1d')
>> import
>> integer(C_INT), value :: n
>> real(C_DOUBLE), dimension(*), intent(out) :: in
>> real(C_DOUBLE), dimension(*), intent(out) :: out
>> integer(C_FFTW_R2R_KIND), value :: kind
>> integer(C_INT), value :: flags
>> end function fftw_plan_r2r_1d
>> type(C_PTR) function fftw_plan_r2r_2d(n0,n1,in,out,kind0,kind1,flags)
>> bind(C, name='fftw_plan_r2r_2d')
>> import
>> integer(C_INT), value :: n0
>> integer(C_INT), value :: n1
>> real(C_DOUBLE), dimension(*), intent(out) :: in
>> real(C_DOUBLE), dimension(*), intent(out) :: out
>> integer(C_FFTW_R2R_KIND), value :: kind0
>> integer(C_FFTW_R2R_KIND), value :: kind1
>> integer(C_INT), value :: flags
>> end function fftw_plan_r2r_2d
>> end interface fftw_plan_gen
>> type(c_ptr) :: p
>> real(c_double), dimension(1,1) :: a
>> p= fftw_plan_r2r_2d(1_c_int,1_c_int, a, a, 0_c_int32_t, 0_c_int32_t,
>> 0_c_int)
>> p= fftw_plan_gen(1_c_int,1_c_int, a, a, 0_c_int32_t, 0_c_int32_t,
>> 0_c_int)
>> write (*,*) transfer(p,1_c_size_t)
>> end program test
Thanks. I will probably not need more versions for various array ranks. I
think that possibility of two different bindings for the same C symbol is
possible only in some TS addendum to Fortran 2008 and not widely
implemented. At least my compilers cannot use it. But I will remember the
solution to pass just the pointer, if I need it.
> I am not sure if you can get away with two different ones with
> the same name and different rank inside the generic. (In case
> you want to allow either 1D or 2D passed to fftw_plan_r2r_2d.)
> More likely, though, you can give them different names, but the
> same bind(name='name') and it will allow it through.
>> p= fftw_plan_r2r_2d(1_c_int,1_c_int, a, a, 0_c_int32_t, 0_c_int32_t,
>> 0_c_int)
>> p= fftw_plan_gen(1_c_int,1_c_int, a, a, 0_c_int32_t, 0_c_int32_t,
>> 0_c_int)
> Another possibility is to pass a c_ptr to the function, and put
> c_loc(a) for each array argument. That is assuming that you don't
> want it to select the generic based on rank.