Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29389 Discussions

how to access a pointer in C as a multi-dimensional array from Fortran??

xu_steve
Beginner
1,085 Views
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.



0 Kudos
6 Replies
JVanB
Valued Contributor II
1,085 Views
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]
0 Kudos
JVanB
Valued Contributor II
1,085 Views
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]
0 Kudos
xu_steve
Beginner
1,085 Views
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

0 Kudos
Arjen_Markus
Honored Contributor II
1,085 Views
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
0 Kudos
Steven_L_Intel1
Employee
1,085 Views
Fortran 2003 introduced pointer bounds remapping, and the Intel compiler supports it as of 12.1.
0 Kudos
xu_steve
Beginner
1,085 Views
Thank you very much
0 Kudos
Reply