- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear,
I want to send a value to a subroutine in c. In subroutine C the value needs to be changed and that change should be kept in fortran. But not work. What do i do?
I greatly appreciate the help!
See example:
---------MAIN FORTRAN---------
program f90callC
use, intrinsic :: iso_c_binding
use interop
implicit none
byte :: i
integer(c_int) :: n
integer(c_int), allocatable, dimension(:) :: vetor
real(c_double) :: val
real(c_float), allocatable, dimension(:) :: array
n=3; val=3.14
allocate(vetor(n))
allocate(array(n))
write(*,*)' before:',val
write(*,*)' ----------------------'
write(*,*)' vector array '
do i=1,n
vetor(i)=2*i-1
array(i)=i**sqrt(2.)-1
write(*,*) vetor(i),array(i)
enddo
write(*,*)' ----------------------'
!void C
call f_function(n,vetor,val,array)
write(*,*)' after:',val
write(*,*)' ----------------------'
write(*,*)' vetor array '
do i=1,n
write(*,*) vetor(i),array(i)
enddo
write(*,*)' ----------------------'
deallocate(vetor)
deallocate(array)
end program f90callC
---------MAIN FORTRAN---------
---------MODULE FORTRAN---------
module interop
interface inter_c_function
subroutine f_function(n, vetor, v, array) bind(c, name='c_function')
use, intrinsic :: iso_c_binding
implicit none
integer(c_int), value :: n
integer(c_int), dimension(n),intent(inout) :: vetor
real(c_double),intent(inout) :: v
real(c_float), dimension(n),intent(inout) :: array
end subroutine
end interface
end module
---------MODULE FORTRAN---------
---------Subroutine in C---------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
/* Prototype */
//int fplusint(int k, int m);
float fmultfloat(float k, float m);
//extern void c_function(int n, int *vetor,double v, float *array);
void c_function(int n, int *vetor,double v, float *array) {
int i;
float aux;
//comandos
v+=(double)2.0;
printf( " Inside C: %f \n",v);
for (i = 0; i < n; ++i)
{
//vetor+=n;
vetor=fplusint(n,vetor);
aux=(float)v;
array=fmultfloat(aux,array);
//array*=(float)v;
printf( " %d %f \n",vetor,array);
}
}
int fplusint(int k, int m)
{
m+=k;
return m;
}
float fmultfloat(float k, float m)
{
m*=k;
return m;
}
---------Subroutine in C---------
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Fortran passes by reference (pointer) by default (value overrides this).
Your Fortran interface declares v without "value" which is correct.
However, your C function is declared with v as value "double v", which is incorrect.
Change your C function to "double* v" then use one level of indirect on v
*v += 2.0;
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear Jim Dempsey,
It worked! Is it similar to using c_f_pointer (c_loc (par2), par1)? How would?
Thank you
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Fortran passes scalar and derived type by reference (default behavior). This is the same as a C pointer. Arrays pass the address of the Fortran array descriptor (however an interface can be declared such that the address of the first cell is passed.
>> c_f_pointer (c_loc (par2), par1)? How would?
There is no need to do that kind of confusing programming. c_f_pointer is generally used to produce a FORTRAN pointer to something allocated or referenced originating inside the C code. An example is a pointer to an array allocated in C. The c_f_pointer constructs the FORTRAN array descriptor.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sorry to bother you again. But I need to know how to pass a type fortran to C and
return with new values. I'm new in C. Example:
-- main fortran --
:
TYPE, BIND(C) :: MYFTYPE
INTEGER(C_INT) :: I, J
REAL(C_FLOAT),ALLOCATABLE,DIMENSION(:) :: S ! Are wrong. how is correct in bind(c)?
END TYPE MYFTYPE
type(MYFTYPE) :: mytype
allocate(S(3))
write(*,*)"F(input) :",mytype
call croutine(mytype)
write(*,*)"C(output):",mytype
:
deallocate(S)
end Program main
-- module fortran --
:
INTERFACE
subroutine croutine(testtype) bind(c, name='routine')
use, intrinsic :: iso_c_binding
implicit none
TYPE, BIND(C) :: MYFTYPE
INTEGER(C_INT) :: I, J
REAL(C_FLOAT),ALLOCATABLE,DIMENSION(:) :: S
END TYPE MYFTYPE
type(MYFTYPE),intent(inout) :: testtype
end subroutine
END INTERFACE
:
-- header c --
typedef struct {
int m, n;
float r(10);
} myctype;
-- c --
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "intervars.h"
/* C global variables */
myctype MYcTYPE;
void routine(myctype MYfTYPE)
{
<code to change MYfTYPE's values and return new values to fortran>
}
thanks a lot.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Look in the IVF documentation, index, array descriptors. Your struct myctype should be replaced with:
[cpp]
struct IVF_ARRAY_DESCRIPTOR_DIM_t
{
intptr_t nElements;
intptr_t byteStrideBetweenElements;
intptr_t lowerBound;
};
struct IVF_ARRAY_DESCRIPTOR_t
{
void* base;
intptr_t element_size;
intptr_t A0_offset;
intptr_t Flags; // 1=allocated/defined, 2 = no deallocation, 4=contiguous
intptr_t nDims;
intptr_t reserved;
struct IVF_ARRAY_DESCRIPTOR_DIM_t Dims[7];
};
// ...
typedef struct
{
int m,n;
struct IVF_ARRAY_DESCRIPTOR_t ArrayDescriptor;
} myctype;
[/cpp]
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
*** CAUTION ***
IVF Array descriptors are not necessarily the same as MS Fortran, nor GFORTRAN, nor xyz Fortran.
For portability, pass the LOC of the first cell of the array and number of cells.
BTW, in FORTRAN, the right most index has the clostes neighbors (backwards from C).
Jim Dempsey
Jim Dempsey
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page