Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

passing C_PTR to fortran

71 views
Skip to first unread message

Hossein

unread,
May 8, 2012, 2:22:28 PM5/8/12
to
Hello All,

I am trying to associate a Fortran pointer to a C pointer array which
is allocated in a C function. I try to do it with type(C_PTR) and then
using C_F_POINTER associate it to a Fortran pointer. This works when I
pass the type(C_PTR) as a function result and it does not work when I
use subroutine.

Here is what I did in C:

//
extern "C"{void *tf_metis_meshtodual( idx_t &ne, idx_t &nn,idx_t
eptr[],idx_t eind[], idx_t &ncommon,idx_t &numflag, void
*cptr_adjncy ) {
int status=0;

idx_t *xadj ,*adjncy;
status = METIS_MeshToDual(&ne, &nn, eptr, eind, &ncommon,
&numflag, &xadj, &adjncy);
if (status==1){
printf(" tf_metis_meshtodual: METIS_MeshToDual METIS_OK= %d
\n",status);
cptr_adjncy= (void *) &adjncy[0];
}else{
printf("tf_metis_meshtodual: problem with METIS_MeshToDual
\n",status);
}
return (void *) &xadj[0];
}}


What I do in Fortran:

interface
type (C_PTR) function tf_metis_meshtodual(ne,nn,eptr,
eind,ncommon,numflag,adjncy) bind(C,name="tf_metis_meshtodual")
import
integer(kind=METIS_IDX_T) :: ne
integer(kind=METIS_IDX_T) :: nn
integer(kind=METIS_IDX_T) :: eptr(*)
integer(kind=METIS_IDX_T) :: eind(*)
integer(kind=METIS_IDX_T) :: ncommon
integer(kind=METIS_IDX_T) :: numflag
type(C_PTR),value :: adjncy
End function tf_metis_meshtodual
end interface

integer(kind=METIS_IDX_T) :: objval=0, i,pr,ierror,ncommon,numflag
integer(kind=C_int) :: status=0
type(C_PTR) :: cptr_adjncy,cptr_xadj

ncommon=1
numflag=0
cptr_xadj=tf_metis_meshtodual(this%metis_mesh%ne,this%metis_mesh
%nn,this%metis_mesh%eptr, &
this%metis_mesh%eind,ncommon,numflag,cptr_adjncy)
if (C_ASSOCIATED(cptr_adjncy)) Call C_F_POINTER(cptr_adjncy,this
%metis_graph%adjncy,[6])
if (C_ASSOCIATED(cptr_xadj)) Call C_F_POINTER(cptr_xadj,this
%metis_graph%xadj,[6])


So, I can get the this%metis_graph%xadj but not the this%metis_graph
%adjncy because cptr_adjncy is not associated.

Thank you.

Ian Harvey

unread,
May 8, 2012, 4:13:58 PM5/8/12
to
On 2012-05-09 4:22 AM, Hossein wrote:
> Hello All,
>
> I am trying to associate a Fortran pointer to a C pointer array which
> is allocated in a C function. I try to do it with type(C_PTR) and then
> using C_F_POINTER associate it to a Fortran pointer. This works when I
> pass the type(C_PTR) as a function result and it does not work when I
> use subroutine.
>
> Here is what I did in C:
>
> //
> extern "C"{void *tf_metis_meshtodual( idx_t&ne, idx_t&nn,idx_t
> eptr[],idx_t eind[], idx_t&ncommon,idx_t&numflag, void
> *cptr_adjncy ) {

If you want this function to pass a pointer back in cptr_adjncy, then
this needs to have an extra level of indirection - void **cptr_adjncy.

(You want to pass a pointer to a pointer.)

References to cptr_adjncy in the function body would then need to be
modified appropriately to account for this.

> int status=0;
>
> idx_t *xadj ,*adjncy;
> status = METIS_MeshToDual(&ne,&nn, eptr, eind,&ncommon,
> &numflag,&xadj,&adjncy);
> if (status==1){
> printf(" tf_metis_meshtodual: METIS_MeshToDual METIS_OK= %d
> \n",status);
> cptr_adjncy= (void *)&adjncy[0];

*cptr_adjncy = (void *) adjncy;

> }else{
> printf("tf_metis_meshtodual: problem with METIS_MeshToDual
> \n",status);

You may want to consider:

*cptr_adjncy = NULL;

here to make sure that the pointer return in the argument is always
sensibly defined.

> }
> return (void *)&xadj[0];
> }}
>
>
> What I do in Fortran:
>
> interface
> type (C_PTR) function tf_metis_meshtodual(ne,nn,eptr,
> eind,ncommon,numflag,adjncy) bind(C,name="tf_metis_meshtodual")
> import
> integer(kind=METIS_IDX_T) :: ne
> integer(kind=METIS_IDX_T) :: nn
> integer(kind=METIS_IDX_T) :: eptr(*)
> integer(kind=METIS_IDX_T) :: eind(*)
> integer(kind=METIS_IDX_T) :: ncommon
> integer(kind=METIS_IDX_T) :: numflag
> type(C_PTR),value :: adjncy

What you have matches the C function as you supplied it. Same comment
applies - when you look at the Fortran syntax the problem is clearer is
a way - an argument with the value attribute cannot be used to return
information to its caller as you are only only "passing" the value.

Along with the change to the C definition of the function:

TYPE(C_PTR) :: adjncy

Better:

TYPE(C_PTR), INTENT(OUT) :: adjncy

(If you supplied INTENT(OUT) and VALUE together previously the compiler
would have complained - which may have let you identify what was going
wrong earlier. Supplying an INTENT attribute is something which is
mandatory in my preferred coding style.)

Hossein

unread,
May 9, 2012, 3:31:29 AM5/9/12
to
Dear Ian,

Thanks very much. It all works fine now.

Cheers
Hossein
0 new messages