- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am trying to call a C function from Fortran.
The fortran code declares a user defined structure type TPATCH, which contains a real pointer.
TYPE TPATCH
REAL,POINTER,DIMENSION(:) ::FIN,FOUT
END TYPE TPATCH
A pointer to TPATCH is then initialized and allocated.
TYPE(TPATCH), POINTER :: LVL_HANDLE
ALLOCATE(LVL_HANDLE)
ALLOCATE(LVL_HANDLE%FIN(1))
ALLOCATE(LVL_HANDLE%FOUT(1))
Arbitrary values are initialized
LVL_HANDLE%FIN(1) = 1
LVL_HANDLE%FOUT(1) = 2
Then the LVL_HANDLE pointer to sent to my C program.
CALL IJK(LVL_HANDLE)
In my C program I create an exact copy of the struct (converting real to float).
typedef struct
{
float *FIN;
float *FOUT;
}TPATCH;
extern "C" void ijk_(TPATCH *LVL_HANDLE){
When I print:
printf("FIN[0] = %e\\n", (LVL_HANDLE->FIN[0]));
It produced the correct answer however when i print:
printf("FOUT[0] = %e\\n", (LVL_HANDLE->FOUT[0]));
I get this segmentation fault:
forrtl: severe (174): SIGSEGV, segmentation fault occurred
I compile the .cu file by:
nvcc -c cudatest1.cu
then compile the .f90 file by:
ifort -c -g fortest.f90
link:
ifort -o test -g fortest.o cudatest1.o -L/usr/local/cuda/lib -lcudart -lstdc++
I am running 32bit linux using ifort version 11.1 and nvcc 3.1
I need to use both ifort anf nvcc as i will be programming in CUDA later.
Does anyone know why I get this segmentation fault?
Any help will be much appreciated.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Detail info about the array descriptor components can be found at the compiler documenation Building Applications / Programming with Mixed Languages / Handling Data Types in Mixed-Language Programming / Handling Arrays and Fortran Array Descriptors. You need to declare FIN and FOUT as a array descriptor struct in the C struct.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Fortran pointers and C pointers are completely different, so it's likely that the segmentation fault is caused by argument's mismatch.
Interoperability between C and Fortran is slightly confusing by the fact that whereas in C almost everything is a pointer (and you can cheat very easily), in Fortran you need the right type/shape/rank combination.
Your definition
[fortran]TYPE(TPATCH), POINTER :: LVL_HANDLE[/fortran]
Should not really be a pointer, but a scalar that is NOT passed by value (which is similar to Fortran's default passing mechanism), so you should simply change it to:
[fortran]TYPE(TPATCH) :: LVL_HANDLE[/fortran]
FIN and FOUT are arrays, so you might want to declare them as such, if you know their size in advance:
[fortran]use ISO_C_BINDING ... integer(C_SIZE_T), parameter :: F_SIZE = 1 type, bind(C) :: TPATCH real, dimension(INT(F_SIZE)) :: FIN, FOUT end type[/fortran]
If you don't know the size in advance, you have the option of using C_PTR, which is the only Fortran type that's interoperable with a C pointer (e.g., a void pointer):
[fortran]use ISO_C_BINDING ... type, bind(C) :: TPATCH type(C_PTR) :: FIN, FOUT end type[/fortran]
The ISO_C_BINDING module contains procedures such as C_LOC and C_F_POINTER to deal with such type.
Finally: the compiler might help you check the argument mismatch, if you provide an explicit interface for the procedure you're trying to call (i.e., a function prototype), as in:
[fortran]use ISO_C_BINDING ... integer(C_SIZE_T), parameter :: F_SIZE = 1 type, bind(C) :: TPATCH real, dimension(INT(F_SIZE)) :: FIN, FOUT end type interface subroutine ijk (LVL_HANDLE, SIZE) import type(TPATCH) :: LVL_HANDLE integer(C_SIZE_T), value :: SIZE end subroutine end interface[/fortran]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page