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.)