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

dynamic array allocated in a c function called from fortran program does not return memory allocated

gourish2011
Beginner
2,144 Views
Hi,
I am calling a c function from a fortran program.
the fortran program passes a c type integer pointer to the c function.
the c function dynamically allocates the memory using the malloc funtion,
however on the return to the main fortran program the memory allocated by the c program in NOT retained.

the following is the c function code followed by the fortran program
....

////////// C function (test.c) ///////////
#include

extern "C" void c_func(int *x)
{
x = (int *) malloc(100*sizeof(int));
}



CCCCCC Fortran calling Program (f_callc.f)CCCCCC

PROGRAM FORT_CALLS_C

IMPLICIT NONE

INTERFACE
SUBROUTINE c_func(xval) BIND(C)
USE, INTRINSIC :: ISO_C_BINDING
TYPE(C_PRT), VALUE :: xval
END SUBROUTINE c_func
END INTERFACE

INTEGER(C_INT), ALLOCATABLE :: X(:)

CALL c_func(C_LOC(X))

DEALLOCATE(X)

STOP
END

is there any solution for this particular problem.

Regards,
Gourish
0 Kudos
1 Solution
jimdempseyatthecove
Honored Contributor III
2,144 Views
Your C function is incorrect. Use

extern "C" void c_func(int **x)
{
*x = (int *) malloc(100*sizeof(int));
}

or better

extern "C" void c_func(int **x, int s)
{
*x = (int *) malloc(s*sizeof(int));
}
**** ALSO ****

Your FORTRAN code is incorrect
The return value is an integer not a FORTRAN array. Your FORTRAN code must convert the integer value into an array descriptor. Also, do not deallocate in FORTRAN what you allocated in C/C++.

PROGRAM FORT_CALLS_C

IMPLICIT NONE

INTERFACE
SUBROUTINE c_func(xval, s) BIND(C) ! ****
USE, INTRINSIC :: ISO_C_BINDING
TYPE(C_PRT), REFERENCE :: xval ! ****
TYPE(C_INT), VALUE :: s! ****
END SUBROUTINE c_func
END INTERFACE

INTEGER(C_INT), ALLOCATABLE :: X(:)
INTEGER(C_PTR) :: pX ! ****


CALL c_func(pX,100)
CALL C_F_POINTER(pX,X, [100])

! *** not here DEALLOCATE(X)
CALL c_func_deallocate(pX,100)

STOP
END


Jim Dempsey

View solution in original post

0 Kudos
10 Replies
jimdempseyatthecove
Honored Contributor III
2,145 Views
Your C function is incorrect. Use

extern "C" void c_func(int **x)
{
*x = (int *) malloc(100*sizeof(int));
}

or better

extern "C" void c_func(int **x, int s)
{
*x = (int *) malloc(s*sizeof(int));
}
**** ALSO ****

Your FORTRAN code is incorrect
The return value is an integer not a FORTRAN array. Your FORTRAN code must convert the integer value into an array descriptor. Also, do not deallocate in FORTRAN what you allocated in C/C++.

PROGRAM FORT_CALLS_C

IMPLICIT NONE

INTERFACE
SUBROUTINE c_func(xval, s) BIND(C) ! ****
USE, INTRINSIC :: ISO_C_BINDING
TYPE(C_PRT), REFERENCE :: xval ! ****
TYPE(C_INT), VALUE :: s! ****
END SUBROUTINE c_func
END INTERFACE

INTEGER(C_INT), ALLOCATABLE :: X(:)
INTEGER(C_PTR) :: pX ! ****


CALL c_func(pX,100)
CALL C_F_POINTER(pX,X, [100])

! *** not here DEALLOCATE(X)
CALL c_func_deallocate(pX,100)

STOP
END


Jim Dempsey
0 Kudos
jimdempseyatthecove
Honored Contributor III
2,144 Views
Note, the func_deallocate(pX,100) might not require the size..
0 Kudos
anthonyrichards
New Contributor III
2,144 Views
There is a Fortran elemental intrinsic function MALLOC, which you could use instead perhaps?
0 Kudos
jimdempseyatthecove
Honored Contributor III
2,144 Views
Anthony,

The OP's post was (likely) sketch code. The real app will likely do something other than simply allocate memory else why not simply use ALLOCATE. There is one exception to this and that is when using a scalable allocator whereby allocations/deallocations do not pass through a unified heap but instead are obtained via a thread distributed database of similar (chunk) sized allocations. The C/C++ code for thisis typically easirer to implement and/or you have ready made libraries/functions to do this.

Jim Dempsey
0 Kudos
gourish2011
Beginner
2,144 Views
yes, it is a sketch code, and I am passing the dynamic variable from the fortran code to an already existing C code which does some bit of processing on a predefined dataset and returns the result in the fortran array.
I was easier to use the existing libraries in C than making the libraries in Fotran from scratch, also there is an added advantage of maintaing libraries in C, so they can be used for some other C programs as well.

Thanks,
Gourish
0 Kudos
gourish2011
Beginner
2,144 Views
the instrunction

TYPE(C_PRT), REFERENCE :: xval ! ****

gives an compiling error which states as

error #6659 : Not an attribute-spec keyword[REFERENCE]

I am using Intel visual fortran 11.1.065 compiler, on visual studio 2008,
is this a feature which is not supported on the above mentioned compiler ?

Gourish
0 Kudos
Steven_L_Intel1
Employee
2,144 Views
There is no such attribute in the language. REFERENCE is, effectively, the default. There is a VALUE attribute that is supported.

If you are using !DEC$ ATTRIBUTES C (I didn't look), which changes the default to VALUE, you would need to use:

!DEC$ ATTRIBUTES REFERENCE :: xval after the declaration as TYPE(C_PTR) (I hope that's what you meant and not C_PRT).

If you use the F2003 C interoperability features, with BIND(C), then reference is the default.
0 Kudos
gourish2011
Beginner
2,144 Views
I changed the fortran program by using !DEC$ ATTRIBUTES REFERENCE :: xval statement, and it worked
perfectly

!!!!!!!!!! Corrected Sample Code !!!!!!!!!!

PROGRAM FORT_CALLS_C

IMPLICIT NONE

INTERFACE
SUBROUTINE c_func(xval, s) BIND(C)
USE, INTRINSIC :: ISO_C_BINDING
TYPE(C_PTR) :: xval ! ****
!DEC$ ATTRIBUTES REFERENCE :: xval ! ****
TYPE(C_INT), VALUE :: s
END SUBROUTINE c_func
END INTERFACE

INTEGER(C_INT), ALLOCATABLE :: X(:)
TYPE(C_PTR) :: pX ! ****

CALL c_func(pX,100)
CALL C_F_POINTER(pX, X, [100])

CALL c_func_deallocate(pX,100)

STOP
END
0 Kudos
Steven_L_Intel1
Employee
2,144 Views
I find that a bit odd - ATTRIBUTES REFERENCE should have no effect there. I notice your C code uses "int" for malloc - this won't work on 64-bit systems.
0 Kudos
jimdempseyatthecove
Honored Contributor III
2,144 Views
Sorry about the reference thing. (and C_PRT vs C_PTR)

The type of object (array) pointed to is immaterial. cast to (int*) or (char*) for the malloc'd memory would make no difference (except for matching the pointer type in the function signature).

Jim
0 Kudos
Reply