 |
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
jjgermis
Joined: 21 Jun 2006 Posts: 404 Location: N�rnberg, Germany
|
Posted: Thu Sep 24, 2009 1:26 pm Post subject: Passing a Fortran type as struct to C |
|
|
In the same forum I mentioned a mix programming topic. This is sorted out. In the next step I would like to call a function in the C program. In oder to do so I need passing a Fortran user defined type as struct to the C subroutine. Only the standard types is explained in the documentaion under Win32 Platform -> Mixed language programming. Or at least fill the components of the struct.
A very simple example will help me to sort this out. Especially the how to handle the pointers
For the sake of completeness I provide the C header-file with the struct definition: Code: | struct triangulateio {
REAL *pointlist; /* In / out */
REAL *pointattributelist; /* In / out */
int *pointmarkerlist; /* In / out */
int numberofpoints; /* In / out */
int numberofpointattributes; /* In / out */
int *trianglelist; /* In / out */
REAL *triangleattributelist; /* In / out */
REAL *trianglearealist; /* In only */
int *neighborlist; /* Out only */
int numberoftriangles; /* In / out */
int numberofcorners; /* In / out */
int numberoftriangleattributes; /* In / out */
int *segmentlist; /* In / out */
int *segmentmarkerlist; /* In / out */
int numberofsegments; /* In / out */
REAL *holelist; /* In / pointer to array copied out */
int numberofholes; /* In / copied out */
REAL *regionlist; /* In / pointer to array copied out */
int numberofregions; /* In / copied out */
int *edgelist; /* Out only */
int *edgemarkerlist; /* Not used with Voronoi diagram; out only */
REAL *normlist; /* Used only with Voronoi diagram; out only */
int numberofedges; /* Out only */
};
#ifdef ANSI_DECLARATORS
void triangulate(char *, struct triangulateio *, struct triangulateio *,
struct triangulateio *);
void trifree(VOID *memptr);
#else /* not ANSI_DECLARATORS */
void triangulate();
void trifree();
#endif /* not ANSI_DECLARATORS */ |
|
|
Back to top |
|
 |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8210 Location: Salford, UK
|
Posted: Thu Sep 24, 2009 4:44 pm Post subject: |
|
|
The Fortran will pass a reference (for anything). I guess that the C would pass a pointer by default so that would match the Fortran OK.
Fortran does not fix the order of the members unless you use a SEQUENCE statement. From memory I think the C order will be OK. If not then a #pragma may be required.
Not sure about any of the details but as usual the best way is just to try it and see what happens |
|
Back to top |
|
 |
jjgermis
Joined: 21 Jun 2006 Posts: 404 Location: N�rnberg, Germany
|
Posted: Sat Sep 26, 2009 3:05 pm Post subject: |
|
|
When one starts searching for mix language programming there are several websites which explains this. However, it seems like the detail syntax is somewhat compiler dependant. I tried a few things using FTN95. The C subroutines are as follows: Code: | #include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct type_t{
int i;
float x;
float *y;
char *str;
};
extern "C" int ctest(char *temp, int Length){
printf("Here is the string written from c code: %s\n", temp);
return 1;
};
extern "C" float mult(float a, float b){
return a*b;
};
extern "C" void write_type(struct type_t xy){
printf("xy.i: %d\n", xy.i);
printf("xy.x: %6.4f\n", xy.x);
printf("xy.y: %6.4f\n", *xy.y);
printf("xy.y: %c\n", *xy.str);
}; | The Fortran programm calling this routines is as follows: Code: | program test
implicit none
C_EXTERNAL CTEST 'ctest'(REF) : INTEGER*4
C_EXTERNAL MULT 'mult'(VAL,VAL) : REAL
C_EXTERNAL WRITE_TYPE 'write_type'(VAL)
C_EXTERNAL ASSIGN_POINTER 'assign_pointer'(REF)
character(len=11) :: string='test phrase'
integer*4 :: returnval
integer*4 :: I
REAL :: A, B, C
type :: type_t
integer :: i
real :: x
real,pointer :: y
character(len=20),pointer :: str !<<<<<< ------ ???????
end type type_t
type(type_t) :: xy
write(*,'("String written from fortan code: ",A)') string
returnval = CTEST(string)
write(*,'("Returned valued from c code: ",i4)') returnval
A=4.0
B=6.0
C = mult(A,B)
write(*,'("MULT: ",2F6.2)') C,(A*B)
xy%i = 6
xy%x = 9.5
xy%y = 20.3
xy%str = 'qwert'//char(0)
call write_type(xy)
end |
Question: How does one pass a string which is a component of a Fortran user defined type (see type_t in the above example)? In the given example only the first character is passed. Is it correct to terminate the string in Fortran with //char(0) before passing? |
|
Back to top |
|
 |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8210 Location: Salford, UK
|
Posted: Sat Sep 26, 2009 5:01 pm Post subject: |
|
|
In C you would need an array of char with the given length rather than a char*. |
|
Back to top |
|
 |
jjgermis
Joined: 21 Jun 2006 Posts: 404 Location: N�rnberg, Germany
|
Posted: Sun Sep 27, 2009 10:38 am Post subject: |
|
|
In the meanwhile I made good progress in using the C-code with FTN95. Passing a C-structure from FTN95 seems to work fine. However, my "arriving" data seem to be wrong. The program requires a list of x- and y-values which must be in pointlist. The latter needs to be dynamically allocated. A part of the module and the subroutine is listed below.
Code: | module cproc
implicit none
C_EXTERNAL TRIANGULATE 'triangulate'(REF,REF,REF,REF)
type :: triangulateio
real,dimension(:),pointer :: pointlist
integer :: numberofpoints
end type triangulateio
end module cproc
subroutine poly(in)
use cproc
implicit none
type(triangulateio),intent(out) :: in
in%numberofpoints = 4
allocate(in%pointlist(in%numberofpoints*2))
in%pointlist(1) = 0.0
in%pointlist(2) = 0.0
in%pointlist(3) = 1.0
in%pointlist(4) = 0.0
in%pointlist(5) = 1.0
in%pointlist(6) = 10.0
in%pointlist(7) = 0.0
in%pointlist(8) = 10.0
return
end subroutine poly
program mesh
use cproc
implicit none
type(triangulateio) :: tri
call poly(tri) ! Initilise tri
! C call: triangulate("pczAevn", &in, &mid, &vorout);
! -> assign the address of in, mid and vorout
call triangulate('pczAevn'//char(0),tri,tri,tri)
end program mesh |
Question: Is the allocation of the array correct (what about malloc)? Are there perhaps any obvious error in the above solution. The equivalent from the C example program is follows:
Code: | in.numberofpoints = 4;
in.pointlist = (REAL *) malloc(in.numberofpoints * 2 * sizeof(REAL));
in.pointlist[0] = 0.0;
in.pointlist[1] = 0.0;
in.pointlist[2] = 1.0;
in.pointlist[3] = 0.0;
in.pointlist[4] = 1.0;
in.pointlist[5] = 10.0;
in.pointlist[6] = 0.0;
in.pointlist[7] = 10.0; |
|
|
Back to top |
|
 |
jjgermis
Joined: 21 Jun 2006 Posts: 404 Location: N�rnberg, Germany
|
Posted: Wed Sep 30, 2009 8:38 am Post subject: |
|
|
Regrettably, I could not resolve the issue of passing the data correct from Fortran to the C program. However, I could get the C program to compile with SCC. Thus, allowing us to build the program and use it as an standalone executealble.
Another advantage of FTN95 is that one can have .c and .f90 code in the same project. The compiler takes automatically care of the linking  |
|
Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|