Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29590 ディスカッション

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

gourish2011
ビギナー
2,558件の閲覧回数
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 件の賞賛
1 解決策
jimdempseyatthecove
名誉コントリビューター III
2,558件の閲覧回数
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

元の投稿で解決策を見る

10 返答(返信)
jimdempseyatthecove
名誉コントリビューター III
2,559件の閲覧回数
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
jimdempseyatthecove
名誉コントリビューター III
2,558件の閲覧回数
Note, the func_deallocate(pX,100) might not require the size..
anthonyrichards
新規コントリビューター III
2,558件の閲覧回数
There is a Fortran elemental intrinsic function MALLOC, which you could use instead perhaps?
jimdempseyatthecove
名誉コントリビューター III
2,558件の閲覧回数
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
gourish2011
ビギナー
2,558件の閲覧回数
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
gourish2011
ビギナー
2,558件の閲覧回数
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
Steven_L_Intel1
従業員
2,558件の閲覧回数
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.
gourish2011
ビギナー
2,558件の閲覧回数
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
Steven_L_Intel1
従業員
2,558件の閲覧回数
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.
jimdempseyatthecove
名誉コントリビューター III
2,558件の閲覧回数
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
返信