# C-interoperable polymorphic classes via pointers

**URL:** <https://fortran-lang.discourse.group/t/c-interoperable-polymorphic-classes-via-pointers/6967>\
**Category:** Uncategorized\
**Created:** [December 10, 2023, 9:04pm UTC](https://fortran-lang.discourse.group/t/c-interoperable-polymorphic-classes-via-pointers/6967 "2023-12-10T21:04:36Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![FedericoPerini](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/federicoperini/32/1750_2.png) [@FedericoPerini](https://fortran-lang.discourse.group/u/FedericoPerini)\
**Post date:** [December 10, 2023, 9:04pm UTC](https://fortran-lang.discourse.group/t/c-interoperable-polymorphic-classes-via-pointers/6967/1 "2023-12-10T21:04:36Z")

</div>

Hello all,

I have a use case of C interoperability (with C++, but could be Python or else) where I want to interface polymorphic classes to C, and I want to avoid writing interfaces to all type-bound functions from the parent class also in the extended classes, when they’re only defined in the parent (maybe abstract) class.

So far I think the best case scenario is to define a pointer to the parent class accessor, like in the following example:

```fortran
module extend_c
   use iso_c_binding
   implicit none

   ! The Fortran classes
   type :: a
      integer :: i = 42
      contains
        procedure :: get_i
   end type a

   type, extends(a) :: b
   end type b

   ! The C opaque pointer classes
   type, bind(C) :: a_c
      type(c_ptr) :: cptr = c_null_ptr
   end type a_c 

   type, bind(C) :: b_c
      type(c_ptr) :: cptr = c_null_ptr
   end type 

   contains

   ! sample function in the parent class
   elemental integer function get_i(this)
      class(a), intent(in) :: this
      get_i = this%i
   end function get_i

   ! its interface is only defined for the interoperable parent class
   integer(c_int) function get_i_c(this) bind(C,name="get_i_c")
      type(a_c), intent(in) :: this
      type(a), pointer :: athis
      call c_f_pointer(this%cptr,athis)
      get_i_c = get_i(athis)
   end function get_i_c 

   ! this is similar to a dynamic_cast
   type(a_c) function get_parent_class(this) result(that) bind(C,name="get_parent_class")
      type(b_c), intent(in), value :: this
      type(b), pointer :: fthis
      type(a), pointer :: fthat
      
      call c_f_pointer(this%cptr,fthis)
      if (.not.associated(fthis)) return

      ! Point to parent class 
      fthat => fthis%a

      ! Save it in C type
      that%cptr = c_loc(fthat)

   end function get_parent_class   

end module extend_c

! This could be a C program
program blabla
  use extend_c
  implicit none

  type(b), pointer :: bx => null()
  type(b_c) :: bc
  type(a_c) :: ac

  allocate(bx)
  bc%cptr = c_loc(bx)

  ac = get_parent_class(bc)
  print *, get_i_c(ac)

end program blabla 

```

This is similar to what a `dynamic_cast` would do in C++.  
The example works great with gfortran, but I’m not sure if:

- is it standard conforming to point to the parent class accessor?
- C++/Fortran gurus (@ivanpribec 🙂 ) is this the best way to achieve that?
- This of course does not work if `type(a)` is `abstract` and I fear this case would be a dead end?

Thank you all!

---

<div class="post-metadata">

**Author:** ![ivanpribec](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ivanpribec/32/3290_2.png) [@ivanpribec](https://fortran-lang.discourse.group/u/ivanpribec)\
**Post date:** [December 11, 2023, 7:37am UTC](https://fortran-lang.discourse.group/t/c-interoperable-polymorphic-classes-via-pointers/6967/2 "2023-12-11T07:37:33Z")

</div>

> [@FedericoPerini](#):
>
> is it standard conforming to point to the parent class accessor?

Not a definitive answer, but here are two sections from MRC (the “red” book):

> The target in a pointer assignment statement may be a subobject of a pointer target. [pg. 50]

> Additionally, an extended type has a **parent component** ; this is a component that has the type and type parameters of the old type and its name is that of the old type. It allows the inherited portion to be referenced as a whole. […] The parent component is particularly useful when invoking procedures that operate on the parent type but which were not written with type extension in mind. [pg. 292]

I’m not 100 % sure if a sub-object only refers to a section of an array, or also to components of derived types (including the parent component).

FWIW, the Intel compilers don’t return an error, nor does the NAG compiler. As a result of [Hyrum’s law](https://www.hyrumslaw.com/), I think we can safely assume this behavior will remain valid.

> [@FedericoPerini](#):
>
> ```auto
> ! Point to parent class 
> fthat => fthis%a
> 
> ! Save it in C type
> that%cptr = c_loc(fthat)
> 
> ```

I tried merging the two statements into one, and it also works:

```fortran
      ! Save it in C type
      that%cptr = c_loc(fthis%a)

```

> [@FedericoPerini](#):
>
> ```fortran
> type(b), pointer :: bx => null()
> type(b_c) :: bc
> 
> ```

In Fortran you should probably have the `target` attribute on the `bc` variable (even if the actual association is with the contents of `bc%cptr`), but don’t know if this is a requirement in this case. In C this is not an issue, since you can point to any variable.

> [@FedericoPerini](#):
>
> This is similar to what a `dynamic_cast` would do in C++.

I think a `dynamic_cast` is more similar to `select type` in Fortran. In C++ upcasting is permitted (when the parent class is public):

```auto
class Parent {
public:
    int i{42};
};

class Child : public Parent {
public:
    Child(int j_) : j(j_) {}
    int j;
};

int get_i(Parent &p) { return p.i; }

int main() {

    Child c{43};
    
    // upcast, dynamic_cast may be used, but unnecessary
    Parent &p = c;

    std::cout << p.i << '\n';
    std::cout << get_i(c) << ' ' << c.j << '\n';
    return 0;
}

```

---

<div class="post-metadata">

**Author:** ![FedericoPerini](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/federicoperini/32/1750_2.png) [@FedericoPerini](https://fortran-lang.discourse.group/u/FedericoPerini)\
**Post date:** [December 11, 2023, 8:21am UTC](https://fortran-lang.discourse.group/t/c-interoperable-polymorphic-classes-via-pointers/6967/3 "2023-12-11T08:21:30Z")

</div>

> [@ivanpribec](#):
>
> FWIW, the Intel compilers don’t return an error, nor does the NAG compiler.

This is great news, it means there’s a reasonable way forward to expose Fortran classes to other object-oriented languages.

The only limitation is we can’t pass actual routines from abstract classes, as [also discussed in this thread](https://fortran-lang.discourse.group/t/call-overridden-procedure-of-abstract-parent-type/590/1). For them, I think there is no other solution than writing interface wrappers for each actual child type.

---

<div class="post-metadata">

**Author:** ![Harper](https://avatars.discourse-cdn.com/v4/letter/h/b5ac83/32.png) [@Harper](https://fortran-lang.discourse.group/u/Harper)\
**Post date:** [December 12, 2023, 6:18am UTC](https://fortran-lang.discourse.group/t/c-interoperable-polymorphic-classes-via-pointers/6967/4 "2023-12-12T06:18:29Z")

</div>

@ivanpribec said “I’m not 100 % sure if a sub-object only refers to a section of an array, or also to components of derived types (including the parent component).” MRC(2018) pg.28 says it can refer to derived types. See also the f2023 standard 19.6.1 that says inter alia “Arrays, including sections, and variables of derived, character, or complex type are objects that consist of zero or more subobjects.” Also “If an object is undefined, at least one (but not necessarily all) of its subobjects are undefined.”
