- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear all,
I like to use from C++ a class which is coded in Fotran inside a modul. I haved tried to pass the pointer from Fortran to C++ and back again later. But this seems not to work, if calling virtual functions.
Here is the code of the base and the dreived class: module.f
[fortran]
MODULE BASE_TYPE
TYPE :: base
real(8) :: num
CONTAINS
final :: base_dtor
procedure :: speak => base_speak
procedure :: init
END TYPE BASE
!
CONTAINS
subroutine base_dtor(this)
TYPE(base), intent(inout) :: this
print *, "base_dtor"
end subroutine
!
subroutine base_speak(this)
CLASS(base), intent(in) :: this
print *, "speak: base ", this%num
end subroutine
!
subroutine init(this, n)
CLASS(base), intent(inout) :: this
real(8), intent(in) :: n
this%num = n
end subroutine
!
END MODULE BASE_TYPE
!
!
MODULE DERIVED_TYPE
USE BASE_TYPE
TYPE, EXTENDS(BASE) :: DERIVED
CONTAINS
final :: derived_dtor
procedure :: speak => derived_speak
END TYPE DERIVED
!
CONTAINS
subroutine derived_dtor(this)
TYPE(derived), intent(inout) :: this
print *, "derived_dtor"
end subroutine
!
subroutine derived_speak(this)
CLASS(derived), intent(in) :: this
print *, "speak: derived ", this%num
end subroutine
!
END MODULE DERIVED_TYPE
[/fortran]
The interface for C++: interface.f
[fortran]
subroutine base_get( cptr )
use iso_c_binding
use base_type
use derived_type
type(c_ptr), intent(out) :: cptr
type(base), pointer :: fptr
allocate(fptr)
cptr=c_loc(fptr)
end subroutine
!
subroutine base_free( cptr )
use iso_c_binding
use base_type
use derived_type
type(c_ptr), intent(in) :: cptr
type(base), pointer :: fptr
call c_f_pointer( cptr, fptr)
deallocate(fptr)
end subroutine
!
subroutine base_init( cptr, num )
use iso_c_binding
use base_type
use derived_type
type(c_ptr), intent(in) :: cptr
real(8), intent(in) :: num
type(base), pointer :: fptr
call c_f_pointer( cptr, fptr)
call fptr%init(num)
end subroutine
!
subroutine base_speak( cptr )
use iso_c_binding
use base_type
use derived_type
type(c_ptr), intent(in) :: cptr
type(base), pointer :: fptr
call c_f_pointer( cptr, fptr)
call fptr%speak
end subroutine
!
!
subroutine derived_get( cptr )
use iso_c_binding
use base_type
use derived_type
type(c_ptr), intent(out) :: cptr
type(derived), pointer :: fptr
allocate(fptr)
cptr=c_loc(fptr)
end subroutine
!
subroutine derived_free( cptr )
use iso_c_binding
use base_type
use derived_type
type(c_ptr), intent(in) :: cptr
type(derived), pointer :: fptr
call c_f_pointer( cptr, fptr)
deallocate(fptr)
end subroutine
!
subroutine derived_init( cptr, num )
use iso_c_binding
use base_type
use derived_type
type(c_ptr), intent(in) :: cptr
real(8), intent(in) :: num
type(derived), pointer :: fptr
call c_f_pointer( cptr, fptr)
call fptr%init(num)
end subroutine
!
subroutine derived_speak( cptr )
use iso_c_binding
use base_type
use derived_type
type(c_ptr), intent(in) :: cptr
type(derived), pointer :: fptr
call c_f_pointer( cptr, fptr)
call fptr%speak
end subroutine
[/fortran]
The C++ test: test_interface.cpp
[cpp]
#include <cstdio>
// function for base
extern "C" void base_get_(void **ptr);
extern "C" void base_free_(void **ptr);
extern "C" void base_init_(void **ptr, const double *);
extern "C" void base_speak_(void **ptr);
// function for derived
extern "C" void derived_get_(void **ptr);
extern "C" void derived_free_(void **ptr);
extern "C" void derived_init_(void **ptr, const double *);
extern "C" void derived_speak_(void **ptr);
// test function
extern "C" void test_interface_(void)
{
void *ptr;
double num;
// the following lines seems to work (the output is correct)
num=10.0;
printf("\\nbase -> base %e\\n", num);
base_get_(&ptr);
base_init_(&ptr, &num);
base_speak_(&ptr);
base_free_(&ptr);
// the following lines seems also to work (the output is correct)
num=20.0;
printf("\\nderived -> derived %e\\n", num);
derived_get_(&ptr);
derived_init_(&ptr, &num);
derived_speak_(&ptr);
derived_free_(&ptr);
//
num=30.0;
printf("\\nderived -> base %e\\n", num);
derived_get_(&ptr);
base_init_(&ptr, &num); // num is set correctly
base_speak_(&ptr); // the base function is called
base_free_(&ptr); // only the destructor of base is called
}
[/cpp]
One problem might be, that I probably need to declare the pointer as CLASS(BASE), pointer ::fptr to deal with virtual functions correctly, but then I cannot convert the c_ptr pointer using the call c_f_pointer( cptr, fptr) subroutine.
Do you have any ideas/workarounds or is there an official way to acces a Fotran class from C++?
Thank you,
Martin
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page