- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, everyone.
I have a pointer dynamically allocated and filled some data in C, and then i need to access it as a multi-dimensional array in Fortran. Say firstly i decalare a global pointer variable and allocate memory for it as follows in C:
doulbe *temp_d;
#define N 10
void c_routine()
{
temp_d=(double*)malloc(N*sizeof(double));
//fill some data to temp_d
}
then in Fortran i try to use temp_d as, for example, temp_d(i,j,k).
I try to use c_f_pointer to do it. For test purpose, i just write the following code and it can compile. But when i run it, i got a segmentation fault.
module c_test
use ios_c_binding
implicit none
type(c_ptr),bind(c,name="temp_d")::temp_d
real(8),pointer::temp_d_fp(:)
integer,parameter::N=10
contains
subroutine init()
call c_f_pointer(temp_d,temp_d_fp,)
end subroutine
end module c_test
program main
use c_test
call init()
write(*,*),temp_d_fp(2)
end program main
I change "real(8),pointer::temp_d_fp(:)" to " real(8),pointer::temp_d_fp", and it will not work too.
Anybody can help me??
BTW, I want to use temp_d as multi-dimensional array of arbitary bound in fortran, for example ,temp_d(-2:2,1:2), I konw for_descriptor_assign may do this, but i need to compile the code on Linux. It seems that intel fortran 11.1 donot support this subroutine on Linux.
I have a pointer dynamically allocated and filled some data in C, and then i need to access it as a multi-dimensional array in Fortran. Say firstly i decalare a global pointer variable and allocate memory for it as follows in C:
doulbe *temp_d;
#define N 10
void c_routine()
{
temp_d=(double*)malloc(N*sizeof(double));
//fill some data to temp_d
}
then in Fortran i try to use temp_d as, for example, temp_d(i,j,k).
I try to use c_f_pointer to do it. For test purpose, i just write the following code and it can compile. But when i run it, i got a segmentation fault.
module c_test
use ios_c_binding
implicit none
type(c_ptr),bind(c,name="temp_d")::temp_d
real(8),pointer::temp_d_fp(:)
integer,parameter::N=10
contains
subroutine init()
call c_f_pointer(temp_d,temp_d_fp,
end subroutine
end module c_test
program main
use c_test
call init()
write(*,*),temp_d_fp(2)
end program main
I change "real(8),pointer::temp_d_fp(:)" to " real(8),pointer::temp_d_fp", and it will not work too.
Anybody can help me??
BTW, I want to use temp_d as multi-dimensional array of arbitary bound in fortran, for example ,temp_d(-2:2,1:2), I konw for_descriptor_assign may do this, but i need to compile the code on Linux. It seems that intel fortran 11.1 donot support this subroutine on Linux.
Link Copied
6 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think you just forgot to invoke c_routine(). At least this works for me:
C code:
[cpp]// c_routine.c #include
double *temp_d;
const size_t N = 10;
void c_routine()
{
int i;
temp_d = (double*)malloc(N*sizeof(double));
for(i = 0; i < N; i++)
{
temp_d = i;
}
}
[/cpp]
Fortran code:
[fortran]! c_test.f90 module c_test use, intrinsic :: iso_c_binding implicit none type(c_ptr), bind(c,name="temp_d") :: temp_d real(c_double), pointer :: temp_d_fp(:) integer, parameter :: N = 10 interface subroutine c_routine() bind(c,name="c_routine") end subroutine c_routine end interface contains subroutine init call c_f_pointer(temp_d,temp_d_fp,)
end subroutine init
end module c_test
program main
use c_test
implicit none
call c_routine
call init
write(*,*) temp_d_fp(2)
end program main
[/fortran]
C code:
[cpp]// c_routine.c #include
Fortran code:
[fortran]! c_test.f90 module c_test use, intrinsic :: iso_c_binding implicit none type(c_ptr), bind(c,name="temp_d") :: temp_d real(c_double), pointer :: temp_d_fp(:) integer, parameter :: N = 10 interface subroutine c_routine() bind(c,name="c_routine") end subroutine c_routine end interface contains subroutine init call c_f_pointer(temp_d,temp_d_fp,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sorry, I didn't take into account the last part of the original post.There are three ways Fortran allows you to set the lower bounds of a pointer. The method you choose depends on your preference and compiler.
The C code is unchanged:
[cpp]// c_routine.c #include
double *temp_d;
const size_t N = 10;
void c_routine()
{
int i;
temp_d = (double*)malloc(N*sizeof(double));
for(i = 0; i < N; i++)
{
temp_d = i;
}
}
[/cpp]
The Fortran code is now:
[fortran]! c_test.f90 module c_test use, intrinsic :: iso_c_binding implicit none type(c_ptr), bind(c,name="temp_d") :: temp_d real(c_double), pointer :: temp_d_fp(:) real(c_double), pointer :: temp_d_1(:,:) real(c_double), pointer :: temp_d_2(:,:) integer, parameter :: N = 10 interface subroutine c_routine() bind(c,name="c_routine") end subroutine c_routine end interface contains subroutine init call c_f_pointer(temp_d,temp_d_fp,)
call c_f_pointer(temp_d,temp_d_1,[N/2,2])
end subroutine init
subroutine remap(oldp,newp)
real(c_double), target :: oldp(-2:,1:)
real(c_double), pointer :: newp(:,:)
newp => oldp
end subroutine remap
end module c_test
program main
use c_test
implicit none
call c_routine
! Create 1-d pointer
call init
write(*,*) temp_d_fp(2)
! First method: use bounds remapping
temp_d_2(-2:2,1:2) => temp_d_fp
write(*,*) temp_d_2(-1,1)
nullify(temp_d_2)
! Second method: specify lower bounds in bounds spec list
temp_d_2(-2:,1:) => temp_d_1
write(*,*) temp_d_2(-1,1)
nullify(temp_d_2)
! Third method: point at assumed-shape dummy
call remap(temp_d_1,temp_d_2)
write(*,*) temp_d_2(-1,1)
end program main
[/fortran]
The C code is unchanged:
[cpp]// c_routine.c #include
The Fortran code is now:
[fortran]! c_test.f90 module c_test use, intrinsic :: iso_c_binding implicit none type(c_ptr), bind(c,name="temp_d") :: temp_d real(c_double), pointer :: temp_d_fp(:) real(c_double), pointer :: temp_d_1(:,:) real(c_double), pointer :: temp_d_2(:,:) integer, parameter :: N = 10 interface subroutine c_routine() bind(c,name="c_routine") end subroutine c_routine end interface contains subroutine init call c_f_pointer(temp_d,temp_d_fp,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, Repeat Offender. Thanks for your help.
But i find the first and second method cannot compile on my computer. My compiler is Intel 11.1 and the compiler error is as follows:
error #6731: object is not a pointer object [temp_d_2]
temp_d_2(-2:2,1:2)=>temp_d_fp
error #6731: object is not a pointer object [temp_d_2]
temp_d_2(-2:,1:)=>temp_d_1
Fortunately the third method do works, but i cannot find the difference of these three methods
But i find the first and second method cannot compile on my computer. My compiler is Intel 11.1 and the compiler error is as follows:
error #6731: object is not a pointer object [temp_d_2]
temp_d_2(-2:2,1:2)=>temp_d_fp
error #6731: object is not a pointer object [temp_d_2]
temp_d_2(-2:,1:)=>temp_d_1
Fortunately the third method do works, but i cannot find the difference of these three methods
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The first two methods use features that have been introduced in Fortran 2008 (or perhaps Fortran 2003
- I am a trifle uncertain here), but are not supported yet by the version of the compiler you are using.
Regards,
Arjen
- I am a trifle uncertain here), but are not supported yet by the version of the compiler you are using.
Regards,
Arjen
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Fortran 2003 introduced pointer bounds remapping, and the Intel compiler supports it as of 12.1.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you very much
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page