I'm delving into Fortran2003 OOP stuff for the first time,
so please bear with me for imprecise using of terminology.
Background: I have an object model defined in C++, with
some 50 classes in a single hierarchy. The classes do not
use virtual procedures, so they're basically pure structs
with methods. They implement a "poor man's run-time type
information" -- have an enumeration of object type in
the header (i.e. base class).
On top of that structure, comes a series of C wrappers
which just translate calls from Fortran to class methods.
And still on top of that structure, lies:
- Fortran translation of C++ class hierarchy
(class foo:public bar -> type, extends(bar):: foo)
- Fortran INTERFACEs (BIND(C)) to above-mentioned C wrappers
So far so good, I've been able to get access to all
relevant methods and all TYPE (i.e. class) attributes.
I am aware that I'm probably outside of the realm of
what's supported by the Standard (and portability),
but that's not the essence of my question.
I've stumbled, however, at F2003 polymorphic types. I don't
see a way to "down-cast" a Fortran pointer, i.e:
type, extends(base):: child
...
end type
class(base), pointer:: b
class(child), pointer:: ch
call GetAnObject(b) !Call to C wrapper
if (b%typeId == TYPE_CHILD) then !my "Poor man's RTTI"
ch => b
end if
The ch => b does not seem to be allowed in Fortran, though.
I know that b is a type(Child), but compiler won't let me.
How can I? (well, I know how I could typecheat, but I'd rather not).
Somewhat widening the topic: I've been contemplating the following
SELECT TYPE example:
http://publib.boulder.ibm.com/infocenter/comphelp/v101v121/index.jsp?topic=/com.ibm.xlf121.aix.doc/language_ref/typecon.html
By the looks of it, it seems that F2003 has a built-in RTTI
mechanism that allows CLASS IS to work...? (Well, the Standard
does not specify implementation, of course, but how else would compiler
know of which child type is the pointer)
So, in my case, since my objects originated in C++ [and I violated
the standard by not using TYPE, BIND(C)], SELECT TYPE wouldn't work,
I gather?
--
Jugoslav
www.xeffort.com
Please reply to the newsgroup.
You can find my real e-mail on my home page above.
|
|
0
|
|
|
|
Reply
|
jdujic (694)
|
11/27/2009 4:17:30 PM |
|
Hello,
Jugoslav Dujic schrieb:
> I'm delving into Fortran2003 OOP stuff for the first time,
> so please bear with me for imprecise using of terminology.
>
> Background: I have an object model defined in C++, with
> some 50 classes in a single hierarchy. The classes do not
> use virtual procedures, so they're basically pure structs
> with methods. They implement a "poor man's run-time type
> information" -- have an enumeration of object type in
> the header (i.e. base class).
>
> On top of that structure, comes a series of C wrappers
> which just translate calls from Fortran to class methods.
>
> And still on top of that structure, lies:
>
> - Fortran translation of C++ class hierarchy
> (class foo:public bar -> type, extends(bar):: foo)
> - Fortran INTERFACEs (BIND(C)) to above-mentioned C wrappers
>
> So far so good, I've been able to get access to all
> relevant methods and all TYPE (i.e. class) attributes.
> I am aware that I'm probably outside of the realm of
> what's supported by the Standard (and portability),
> but that's not the essence of my question.
>
> I've stumbled, however, at F2003 polymorphic types. I don't
> see a way to "down-cast" a Fortran pointer, i.e:
>
> type, extends(base):: child
> ...
> end type
>
> class(base), pointer:: b
> class(child), pointer:: ch
>
> call GetAnObject(b) !Call to C wrapper
> if (b%typeId == TYPE_CHILD) then !my "Poor man's RTTI"
> ch => b
> end if
>
> The ch => b does not seem to be allowed in Fortran, though.
> I know that b is a type(Child), but compiler won't let me.
> How can I? (well, I know how I could typecheat, but I'd rather not).
Presumably, your pointer b will have been allocated with a dynamic type
of child within GetAnObject (if not, the type of b will not even
be known at run time). Once that has been done, you can use
the SELECT TYPE construct as mentioned below:
SELECT TYPE(b)
TYPE IS (child)
ch => b
TYPE IS (...) ! other extensions
...
END SELECT
Note that TYPE IS clauses are what is called RTTI, while CLASS IS
clauses probably should be called RTCI ...
>
> Somewhat widening the topic: I've been contemplating the following
> SELECT TYPE example:
>
> http://publib.boulder.ibm.com/infocenter/comphelp/v101v121/index.jsp?topic=/com.ibm.xlf121.aix.doc/language_ref/typecon.html
>
>
> By the looks of it, it seems that F2003 has a built-in RTTI
> mechanism that allows CLASS IS to work...? (Well, the Standard
> does not specify implementation, of course, but how else would compiler
> know of which child type is the pointer)
>
> So, in my case, since my objects originated in C++ [and I violated
> the standard by not using TYPE, BIND(C)], SELECT TYPE wouldn't work,
> I gather?
Since you do not show the implementation of GetAnObject, I cannot tell
whether you actually have violated the standard (although I suspect it
might be rather difficult if not impossible for a C routine to do
typed allocation). The type base and its extensions cannot themselves
be BIND(C), but are of course allowed to have interoperable components.
So you might have
type :: base
type(c_ptr) :: cbase
type(c_funptr) :: cmethod
end type
and the subroutine GetAnObject is better implemented in Fortran
e.g.
subroutine getanobject(this)
class(base), pointer :: this ! allocatable probably is better
type(c_ptr) :: cbase
type(c_funptr) :: cmethod
integer :: typeid
cbase = ... ! pointer to C object
cmethod = ... ! function pointer to type-specific method (if
! so defined in C++ substrate)
typeid = ... ! poor man's RTTI, now encapsulated
select case(typeid)
case(1)
allocate(base :: this)
case(2)
allocate(child :: this)
: ! etc
end select
! cannot do the following unless base is associated
base%cbase = cbase
base%cmethod = cmethod
end subroutine
where I've not bothered to specify the available C calls. Polymorphic
execution of the methods might be done via
subroutine do_stuff(this)
class(base) :: this
procedure(c_do_stuff), pointer :: cproc
call c_f_procpointer(this%cmethod, cproc)
call cproc(this%cbase, ...) ! dispatch to C method
end do_stuff
An interoperable interface for c_do_stuff must of course be provided;
if the methods' signature varies by type, multiple interfaces must
be declared, and it might be more economic to use a set of procedure
pointers cproc_1, cproc_2, ... which are declared as global variables.
And you again need to use SELECT TYPE to perform proper dispatching.
HTH
Reinhold
>
> --
> Jugoslav
> www.xeffort.com
> Please reply to the newsgroup.
> You can find my real e-mail on my home page above.
|
|
0
|
|
|
|
Reply
|
Reinhold
|
11/27/2009 5:16:33 PM
|
|
|
1 Replies
403 Views
(page loaded in 0.046 seconds)
|