- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
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
1 Solution
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
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
Link Copied
10 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Note, the func_deallocate(pX,100) might not require the size..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There is a Fortran elemental intrinsic function MALLOC, which you could use instead perhaps?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
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
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page