Polymorphism and C++ interfacing

Polymorphism and C++ interfacing

Hello, 
In the following code which is part of a C++/Fortran interface, I need to pass fortran pointers to various types, and see proper descriptors at the C++ level, then set those descriptors so that upon return, fortran will see the correct data.  This code works only when qresult and temp are defined as specific type pointers but not with the polymorphic ones I am trying to use below. My intent is to associate a fortran pointer to a type or array from C++, and not to copy the contents. I would appreciate any input on a possible solution.

[code]
interface 
subroutine tDBGet(ctx, query, qtype, qresult, err)
import ContextType
type(ContextType), intent(inout):: ctx
character(len=*), intent(in):: query
character(len=*), intent(in):: qtype
class(*), intent(inout):: qresult(:)
integer, intent(inout):: err
end subroutine
end interface

type DatabaseAccessType  ! type contained within ContextType
procedure(tDBGet), pointer, nopass:: dbGet ! DB query function pointer to obtain database information
end type 

integer function prDBGetPtrRefS(ctx, query, qtype, qresult)
!DEC$ ATTRIBUTES NO_ARG_CHECK :: qresult
use device,only: DeviceType
implicit none
type(ContextType), intent(inout):: ctx
character(len=*), intent(in):: query
character(len=*), intent(in):: qtype
class(*), pointer, intent(inout):: qresult  ! works only with type(DeviceType), pointer, intent(inout):: qresult
class(*), pointer :: temp(:) ! works only with type(DeviceType), pointer, intent(inout):: temp(:)

call ctx%db%dbGet(ctx, query, qtype, temp, prDBGetPtrRefS)
! call ctx%db%dbGet(ctx, query, qtype, qresult, prDBGetPtrRefS)
qresult => temp(1)
end function[/code]

7 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Amendment, since I can't edit original post: 
- Apologies for not using fortran enclosures, code looks like text 

I assume you are basing your C++ code on the array descriptor layout we document. That doesn't work for polymorphic types, I'm afraid. I would recommend passing C_LOC of items and dealing with them as straight data pointers in C++. Even with the enhancements coming in Fortran 2015 to C interoperability, polymorphic data is still off limits.

Steve - Intel Developer Support

I'm not quite sure what you want to do.  To help us understand, could you perhaps provide a snippet of the relevant C++ code?

Fortran pointers and C[++] pointers are (mostly) different beasts - and consequently they are not interoperable.  Similarly Fortran polymorphic objects and C++ base type pointers or references are not interoperable.  However Fortran does have a derived type that can be used to store a C pointer, and you can get the C address of certain Fortran objects (not polymorphic ones, but you can get around that by wrapping the polymorphic object in another type).

Sometimes it is sufficient to pass the C address of a Fortran object as an opaque token (a handle) to C[++] code and then use that token in calls back to Fortran to identify the relevant object in subsequent operations.

Steve,

Thank you for the suggestion, and I do indeed base my interface on the documented fortran descriptors. Will C_LOC(ptr) of a local pointer variable such as :  type(DeviceType), pointer:: ptr   return the location of the pointer descriptor? I know that those locations vary greatly depending on how the subroutine is defined. For normal subs they are not on the stack, and for recursive ones they are. Will C_LOC provide me with the current location of the descriptor the fortran sub will see upon return, or will I get a copy?

I also noticed that using the above code, the real pointer descriptor for a (:) pointer is one descriptor (with alignment) before the one passed to C++, so if I set the descriptor passed to C++, fortran will still end up with an undefined pointer/array. Any comments on how to set this in an official way without using anything undocumented that might change?

@Ianh : Thanks for the idea of wrapping polymorpic types, however, the approach of using opaque types is not suitable in this case, since we need to set fortran pointers to external data, that can be quite large, and that may need also to be modified from C++. On the other hand, using a data-copy method would make this interface quite slow.

C_LOC will give you the pointer to the data, not the descriptor. Do not do anything to change the descriptor passed by Fortran in your C++ code. Again, future features will give you some access to Fortran pointers, but again not for polymorphic.

Steve - Intel Developer Support

Leave a Comment

Please sign in to add a comment. Not a member? Join today