Prev: Write to file from DLL
Next: Error LNK2019
From: Jared Ahern on 19 Aug 2007 19:36 Hello again! Ok, so I finally put a testcase together. This demonstrates a basic problem that I have when using iso_c_binding, and calling Fortran procedures from C. Here is the Fortran side: MODULE test USE, INTRINSIC :: iso_c_binding, ONLY: c_float, c_int IMPLICIT NONE TYPE, BIND(C) :: foo REAL(c_float) :: c END TYPE foo CONTAINS TYPE(foo) FUNCTION power_f(a,b) BIND(C) TYPE(foo), INTENT(IN) :: a INTEGER(c_int), INTENT(IN) :: b power_f%c = a%c ** b END FUNCTION power_f END MODULE test Here is the C side: #include <stdio.h> typedef struct foo { float c; } foo; extern foo power_f(const foo* const a,const int* const b); #ifdef __G95__ extern void g95_runtime_start(int argc, char *argv[]); extern void g95_runtime_stop(); #endif int main(int argc, char *argv[]) { #ifdef __G95__ g95_runtime_start(argc,argv); #endif foo fx = {3.0}, fy; int i = 2; printf("fx 1 = %f \n",fx.c); printf("i = %i\n",i); fy = power_f(&fx,&i); printf("fx 2 = %f \n",fx.c); printf("fy = power_f(&fx,&i): %f\n",fy.c); #ifdef __G95__ g95_runtime_stop(); #endif return 0; } When I compile and run this program, I get output like this (plus an irrelevant warning): % gcc -Wall -Wextra -pedantic -std=c89 -D__G95__ -c ctest.c % g95 -Wall -Wextra -std=f2003 -c flib.F90 % g95 -o ctest.x ctest.o flib.o fx 1 = 3.000000 i = 2 fx 2 = 1.000000 fy = power_f(&fx,&i): 1.000000 As you can see, the call to power_f not only gave the wrong answer, but it modified the input argument. My questions would be: 1) Have I done anything incorrectly? 2) What can I do to fix this? I have a much larger library of which this is an example, and trying to debug its C bindings has left me quite perplexed. These results were with linux/x84_64/g95, but linux/x86_64/ifort also has errors, and osx/ppc64/g95 has problems on similar testcases. In my main library, I seem to have more problems with types that contain a scalar real, but I have seen problems with types containing fixed-length arrays of reals as well. Operations other than exponentiation can also cause problems. Any and all thoughts anyone has would be greatly appreciated! Thanks! Jared
From: robert.corbett on 19 Aug 2007 22:58 On Aug 19, 4:36 pm, Jared Ahern <jared.ah...(a)gmail.com> wrote: > Hello again! > > Ok, so I finally put a testcase together. This demonstrates a basic > problem that I have when using iso_c_binding, and calling Fortran > procedures from C. Here is the Fortran side: > > MODULE test > USE, INTRINSIC :: iso_c_binding, ONLY: c_float, c_int > IMPLICIT NONE > > TYPE, BIND(C) :: foo > REAL(c_float) :: c > END TYPE foo > > CONTAINS > > TYPE(foo) FUNCTION power_f(a,b) BIND(C) > TYPE(foo), INTENT(IN) :: a > INTEGER(c_int), INTENT(IN) :: b > power_f%c = a%c ** b > END FUNCTION power_f > > END MODULE test > > Here is the C side: > > #include <stdio.h> > > typedef struct foo { float c; } foo; > extern foo power_f(const foo* const a,const int* const b); > > #ifdef __G95__ > extern void g95_runtime_start(int argc, char *argv[]); > extern void g95_runtime_stop(); > #endif > > int main(int argc, char *argv[]) { > #ifdef __G95__ > g95_runtime_start(argc,argv); > #endif > foo fx = {3.0}, fy; > int i = 2; > printf("fx 1 = %f \n",fx.c); > printf("i = %i\n",i); > fy = power_f(&fx,&i); > printf("fx 2 = %f \n",fx.c); > printf("fy = power_f(&fx,&i): %f\n",fy.c); > #ifdef __G95__ > g95_runtime_stop(); > #endif > return 0; > > } > > When I compile and run this program, I get output like this (plus an > irrelevant warning): > > % gcc -Wall -Wextra -pedantic -std=c89 -D__G95__ -c ctest.c > % g95 -Wall -Wextra -std=f2003 -c flib.F90 > % g95 -o ctest.x ctest.o flib.o > fx 1 = 3.000000 > i = 2 > fx 2 = 1.000000 > fy = power_f(&fx,&i): 1.000000 > > As you can see, the call to power_f not only gave the wrong answer, > but it modified the input argument. My questions would be: > > 1) Have I done anything incorrectly? > 2) What can I do to fix this? > > I have a much larger library of which this is an example, and trying > to debug its C bindings has left me quite perplexed. These results > were with linux/x84_64/g95, but linux/x86_64/ifort also has errors, > and osx/ppc64/g95 has problems on similar testcases. In my main > library, I seem to have more problems with types that contain a scalar > real, but I have seen problems with types containing fixed-length > arrays of reals as well. Operations other than exponentiation can > also cause problems. > > Any and all thoughts anyone has would be greatly appreciated! > > Thanks! > Jared I got the following results with the Sun Studio 12 f95 compiler: ../a.out fx 1 = 3.000000 i = 2 fx 2 = 3.000000 fy = power_f(&fx,&i): 9.000000 The program did not compile with the Sun Studio 11 version of the compiler. Bob Corbett
From: Tobias Burnus on 20 Aug 2007 02:31 > I got the following results with the Sun Studio 12 f95 compiler: > > ./a.out > fx 1 = 3.000000 > i = 2 > fx 2 = 3.000000 > fy = power_f(&fx,&i): 9.000000 I get the same result as sunf95 on x86-64 with gfortran 4.3 (-m32 and - m64): fy = power_f(&fx,&i): 9.000000 (It does not compile with 4.2 as ISO C Bindings are only supported since 4.3/2 July 2007.) Tobias
From: David Thompson on 9 Sep 2007 18:32 On Sun, 19 Aug 2007 16:36:52 -0700, Jared Ahern <jared.ahern(a)gmail.com> wrote: > Ok, so I finally put a testcase together. This demonstrates a basic > problem that I have when using iso_c_binding, and calling Fortran > procedures from C. Here is the Fortran side: > TYPE, BIND(C) :: foo > REAL(c_float) :: c > END TYPE foo > TYPE(foo) FUNCTION power_f(a,b) BIND(C) > TYPE(foo), INTENT(IN) :: a > INTEGER(c_int), INTENT(IN) :: b > power_f%c = a%c ** b > END FUNCTION power_f > Here is the C side: > > #include <stdio.h> > > typedef struct foo { float c; } foo; > extern foo power_f(const foo* const a,const int* const b); > Aside: it is useless clutter in C to put a 'top-level' const on a parameter (= dummy) in a _declaration_; these are the ones immediately adjacent to the name(s). A _pointer to_ const OTOH is important: extern foo power_f (const foo * a, const int * b); is EXACTLY the same (and equally correct) to C. > foo fx = {3.0}, fy; > int i = 2; > printf("fx 1 = %f \n",fx.c); > printf("i = %i\n",i); > fy = power_f(&fx,&i); > printf("fx 2 = %f \n",fx.c); > printf("fy = power_f(&fx,&i): %f\n",fy.c); > When I compile and run this program, <snip> > As you can see, the call to power_f not only gave the wrong answer, > but it modified the input argument. My questions would be: > > 1) Have I done anything incorrectly? > 2) What can I do to fix this? > Returning 'struct' types in C has long been an area of implementation dependence. Most compilers pass the address of a temporary as an extra, hidden argument (usually first), but some put in register(s) a struct small enough to fit (as yours does). Sometimes this choice is selectable by a compiler option. I haven't worked with any significant Fortran functions returning derived types, but since the issues of compiling to machine code are the same I would bet that similar situations arise. > I have a much larger library of which this is an example, and trying > to debug its C bindings has left me quite perplexed. These results > were with linux/x84_64/g95, but linux/x86_64/ifort also has errors, > and osx/ppc64/g95 has problems on similar testcases. In my main With which C compiler(s)? gcc? same release as g95? icc? other? I would first check that the Fortran compiler(s)/version(s)/option(s) you are using (each) supports BIND(C) _with the specific C compiler(s)/version(s)/option(s) you are using_. If that still doesn't work, and no one else familiar with your specific compilers/versions has offered more specific advice, I would try looking at the generated assembler (or machine) on both sides for simple examples like the testcase you posted and see exactly what it's doing (and thus what it's doing wrong). > library, I seem to have more problems with types that contain a scalar > real, but I have seen problems with types containing fixed-length > arrays of reals as well. Operations other than exponentiation can > also cause problems. > - formerly david.thompson1 || achar(64) || worldnet.att.net
|
Pages: 1 Prev: Write to file from DLL Next: Error LNK2019 |