Passing and retrieving from fortran arbitrary data through a C void*

I apologise in advance for the very long message.

I am seeking expertise in order to determine if what I am doing is safe/correct, or if alternatives exists.

I have a C library that can hold a user-pointer (void*) to arbitrary C data, so that the user can set and retrieve this pointer through the library and perform appropriate casting back to the original user-defined type in order to access the data.
Imagine the following interface for simplification:

void set_pointer(void* user_ptr);
void* get_pointer();

I want to make a Fortran interface that allows the user to set this void* to arbitrary (C-interoperable) Fortran derived-types through Fortran as well.

The interface to the C code is relatively straight-forward using the iso_c_binding intrinsic module:

interface
    subroutine c_set_pointer(usr_ptr) bind(C, name="set_pointer")
        use, intrinsic :: iso_c_binding
        implicit none
        type(c_ptr), value, intent(in) :: usr_ptr
    end subroutine c_set_pointer
end interface

interface
    function c_get_pointer() result(usr_ptr) bind(C, name="get_pointer")
        use, intrinsic :: iso_c_binding
        implicit none
        type(c_ptr) :: usr_ptr
    end function c_get_pointer
end interface

Now imagine I have an arbitrary Fortran derived type (C-interoperable):

type, bind(C) :: UserData
    integer :: i
    real :: f
end type UserData

Now, setting the pointer is not so difficult, I guess, using assumed-type and c_loc:

subroutine set_pointer(data)
    use, intrinsic :: iso_c_binding
    implicit none
    type(*), target, intent(in) :: data

    call c_set_pointer(c_loc(data))
end subroutine set_pointer

Note I could use assumed-type directly in the interface of c_set_pointer and bypass the Fortran wrapper, but my goal would also be (if even possible) to make this pure Fortran 2003, and assumed-type is 2018 (I think).

It gets complicated when trying to retrieve the user-pointer as there is no Fortran equivalent to void* (to my knowledge), and the data could be any derived-type:

  • It could simply return the type(c_ptr) and let the user c_f_pointer it back to the c-interoperable user-defined type (Here UserData, for the example), but that forces the use of iso_c_binding by the user and I would prefer to avoid it.
  • I do not know any way to inform the retrieval function of the expected user-defined type so that it could do the manipulation described above automatically and directly return a pointer to the user-defined type.
  • As the user-pointer is an arbitrary derived-type, the retrieval function could return an unlimited polymorphic pointer class(*), pointer, but this cannot be used with c_f_pointer with the type(c_ptr) returned by the C interface.

I did find a way to bypass the last point by associating the C pointer to a “byte array?”:

function get_pointer() result(usr_ptr)
    use, intrinsic :: iso_c_binding
    implicit none
    class(*), pointer :: usr_ptr
    type(c_ptr) :: cptr
    character(len=:), pointer :: data

    cptr = c_get_pointer()
    call c_f_pointer(cptr, data) ! This seems to correctly associate the "byte array" to the user-pointer address
    print *, len(data) ! This gives a 0-length character (?)
    print *, c_loc(data) ! This gives the correct memory address of the user-pointer
                         ! But c_loc will fail if "data" is explicitly "len=0",
                         ! but works with "len=:" although len(data) gives 0 (?)
    usr_ptr => data
end function get_pointer

I used Apple clang 15.0.0 (1500.3.9.4) on a Mac M1 to test that code, and it seems to give the expected result, as I was able to correctly access the components of the user-defined type.
It also worked with gfortran 13.2.0 (Still on Mac M1).

implicit none
type(UserData) :: data
type(UserData), pointer :: data_ptr
data = UserData(f = 3.14, i = 42)

call set_pointer(data)
data_ptr => get_pointer()
print *, data_ptr%f ! prints "3.14"
print *, data_ptr%i ! prints "42"

My question(s) is then:

  • Is that a correct (will it work for every compiler?) and safe way to proceed, and the limitation of c_f_pointer with class(*) can be bypassed that way using pointers?
  • Can this be made pure Fortran 2003, as mentioned above (replacing the use of type(*)?)
  • Can this be further extended in order to get rid of the bind(C) limitation on the user-defined type? (Although I don’t think so, as that would allow the use of allocatable arrays and such, and the size of such arrays would be lost)
  • Am I missing anything else?

Thank you for your help.

New contributor

Gaétan JALIN is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật