[J3] [EXTERNAL] Getting c_ptr for type(*), dimension(..)
Clune, Thomas L. (GSFC-6101)
thomas.l.clune at nasa.gov
Tue Nov 15 14:09:24 UTC 2022
Hi Jeff,
The assumed rank aspect is not an issue; it merely requires a tedious use of a SELECT RANK construct. But the TYPE(*) aspect is quite problematic.
The obstacles to doing this in Fortran are 2-fold (at least):
1. TYPE(*) cannot be a pointer, which begs the question of what the declared type of the pointer you were hoping to obtain? If you have a list of all allowed types, you might envisions somehow having a BLOCK for each type and establishing a different declared pointer in each section, or somehow using CLASS(*), POINTER …
2. A TYPE(*) argument cannot be the selector in SELECT TYPE, which undermines the strategy hinted at in (1).
OTOH, if you want to stay within Fortran, why not use CLASS(*)? Then the above approach will work:
module foo
implicit none
contains
subroutine f(x, y)
use iso_c_binding
class(*), target :: x(..)
class(*), pointer :: y(..)
select rank (x)
rank (0)
select rank (y)
rank (0)
y => x
end select
rank (1)
select rank (y)
rank (1)
y => x
end select
! ...
end select
end subroutine f
end module foo
program main
use foo
integer, target :: x
integer, target :: x1(5)
class(*), pointer :: y
class(*), pointer :: y1(:)
x = 5
x1 = 3
call f(x, y)
call f(x1,y1)
end program main
From: J3 <j3-bounces at mailman.j3-fortran.org> on behalf of j3 <j3 at mailman.j3-fortran.org>
Reply-To: j3 <j3 at mailman.j3-fortran.org>
Date: Tuesday, November 15, 2022 at 6:00 AM
To: J3 List <j3 at j3-fortran.org>
Cc: Jeff Hammond <jehammond at nvidia.com>
Subject: [EXTERNAL] [J3] Getting c_ptr for type(*), dimension(..)
Am I missing something or is it not possible to obtain a Fortran pointer for a type(*), dimension(..) argument without going through C?
I am trying to write a generic interface for a callback, i.e. one that has type(*), dimension(..) arguments. Inside of my callback, I know what the type and shape are going to be, and therefore can assign them to an appropriate pointer, which I can then operate on appropriately.
This is easily done with a C function that reads the base address from the CFI_cdesc_t, but I cannot figure out how to do it entirely within Fortran. Did I miss something or is it impossible?
If it is currently impossible to do this without using C, is it unreasonable to ask that we add a feature to make it possible without writing the C conversion function?
Thanks,
Jeff
! #include “ISO_Fortran_binding.h”
! void get_cptr(CFI_cdesc_t * x, void ** y) { *y = x->base_addr; }
module f
interface
subroutine get_cptr(x,y) bind(C)
use, intrinsic :: iso_c_binding, only : c_ptr
implicit none
type(*), dimension(..), intent(in) :: x
type(c_ptr), intent(out) :: y
end subroutine
end interface
end module f
module i
abstract interface
subroutine M_User_function(i, o, n, d)
use, intrinsic :: iso_c_binding, only : c_ptr
implicit none
type(*), dimension(..), intent(in) :: i
type(*), dimension(..), intent(inout) :: o
integer, intent(in) :: n
type(c_ptr), intent(in) :: d
end subroutine
end interface
end module i
module x
contains
subroutine X_function(i, o, n, d)
use, intrinsic :: iso_c_binding, only : c_ptr, c_f_pointer
use f, only : get_cptr
implicit none
type(*), dimension(..), intent(in) :: i
type(*), dimension(..), intent(inout) :: o
integer, intent(in) :: n
type(c_ptr), intent(in) :: d
type(c_ptr) :: cpi, cpo
integer, dimension(:), pointer :: fpi, fpo
! not allowed to do this:
! call c_f_pointer(i,fpi,[size(i)])
! call c_f_pointer(o,fpo,[size(o)])
call get_cptr(i,cpi)
call get_cptr(o,cpo)
call c_f_pointer(cpi,fpi,[size(i)])
call c_f_pointer(cpo,fpo,[size(o)])
end subroutine
end module x
program main
use i
use x
implicit none
procedure(M_User_function), pointer :: fp => NULL()
fp => X_function
end program main
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.j3-fortran.org/pipermail/j3/attachments/20221115/606f9f26/attachment-0003.htm>
More information about the J3
mailing list