From: John N. on 9 Apr 2010 16:28 On Apr 9, 3:20 pm, Gordon Sande <Gordon.Sa...(a)EastLink.ca> wrote: > On 2010-04-09 17:07:42 -0300, "John N." <ort...(a)gmail.com> said: > > > > > On Apr 9, 2:57 pm, "John N." <ort...(a)gmail.com> wrote: > >> On Apr 9, 2:27 pm, Tim Prince <tpri...(a)myrealbox.com> wrote: > > >>> On 4/9/2010 12:06 PM, John N. wrote: > > >>>> invokeF_C.cpp > >>>> **************************************** > >>>> #include<vector> > > >>>> struct pass{ > >>>> int lenc; > >>>> float* c; > >>>> }; > > >>>> void simulation( struct pass* arrays ); > > >>>> int main(){ > >>>> std::vector< float> cVector(12); > >>>> pass arrays; > >>>> arrays.lenc = cVector.size(); > >>>> arrays.c =&cVector[0]; > >>>> simulation(&arrays ); > >>>> } > >>>> **************************************** > > >>>> invokeF_F.f03 > >>>> **************************************** > >>>> subroutine simulation(arrays) bind(c) > >>>> use iso_c_binding > >>>> type, bind(c) :: pass > >>>> integer (c_int) :: lenc > >>>> type (c_ptr) :: c > >>>> end type pass > >>>> type (pass), intent(in) :: arrays > >>>> real (c_float), pointer :: c_array(:) > > >>>> ! associate c_array with an array allocated in C > >>>> call c_f_pointer( arrays%c, c_array, (/arrays%lenc/) ) > >>>> end subroutine simulation > >>>> **************************************** > > >>> You've omitted the extern "C" in your .cpp file. It's iso_c_binding, > >>> not _c++_binding, so the linker must see a C function declaration on > >>> both sides. > > >>> -- > >>> Tim Prince > > >> Tim, > > >> Ah, I forgot that when writing my example. Thanks for the fast > >> response. > > >> Do you have any tips for the best way to build the fortran code as a > >> library and link that with the c++ code? I still can't get any of the > >> command line commands I try to work properly... > > >> John N. > > >> invokeF_C.cpp > >> **************************************** > >> #include<vector> > > >> struct pass{ > >> int lenc; > >> float* c; > > >> }; > > >> extern "C" void simulation( struct pass* arrays ); > > >> int main(){ > >> std::vector< float> cVector(12); > >> pass arrays; > >> arrays.lenc = cVector.size(); > >> arrays.c =&cVector[0]; > >> simulation(&arrays );} > > >> **************************************** > > > This may be very wrong, but this is one of the things I was trying to > > do: > > > $ g++ -c invokeF_C.cpp > > $ gfortran -c invokeF_F.f03 > > $ g++ -o test invokeF_C.o invokeF_F.o > > "test" is a bad name of a Unix executable as it will conflict with one of > the heavily use shell commands. Try something like "F95_with_C_Test" which > is more in the spirit of your other names. > > When you have "test" problems it can be very mysterious! > > > Which returns: > > > invokeF_F.o: In function `simulation': > > invokeF_F.f03:(.text+0xad): undefined reference to > > `__iso_c_binding_c_f_pointer_r4' > > > Do I need some other flags passed to g++ to tell it that I am using a > > fortran created object file? Can I build the fortran file as a > > library? Am I just missing some big step? > > > If you can't tell by now, I am not very familiar with these things, > > unfortunately. > > > John N. > > Oops, I did not realize that might pose problems! I updated the name of the executable. I get the same error: $ g++ -c invokeF_C.cpp $ gfortran -c invokeF_F.f03 $ g++ -o Invoke_F_with_C_Test invokeF_C.o invokeF_F.o Produces: invokeF_F.o: In function `simulation': invokeF_F.f03:(.text+0xad): undefined reference to `__iso_c_binding_c_f_pointer_r4' collect2: ld returned 1 exit status John N.
From: Craig Powers on 9 Apr 2010 17:36 John N. wrote: > > This may be very wrong, but this is one of the things I was trying to > do: > > $ g++ -c invokeF_C.cpp > $ gfortran -c invokeF_F.f03 > $ g++ -o test invokeF_C.o invokeF_F.o > > Which returns: > > invokeF_F.o: In function `simulation': > invokeF_F.f03:(.text+0xad): undefined reference to > `__iso_c_binding_c_f_pointer_r4' > > Do I need some other flags passed to g++ to tell it that I am using a > fortran created object file? Can I build the fortran file as a > library? Am I just missing some big step? > > If you can't tell by now, I am not very familiar with these things, > unfortunately. I think if you use g++ as the driver, you may need to link against libgfortran.
From: John N. on 9 Apr 2010 19:02 On Apr 9, 4:36 pm, Craig Powers <craig.pow...(a)invalid.invalid> wrote: > John N. wrote: > > > This may be very wrong, but this is one of the things I was trying to > > do: > > > $ g++ -c invokeF_C.cpp > > $ gfortran -c invokeF_F.f03 > > $ g++ -o test invokeF_C.o invokeF_F.o > > > Which returns: > > > invokeF_F.o: In function `simulation': > > invokeF_F.f03:(.text+0xad): undefined reference to > > `__iso_c_binding_c_f_pointer_r4' > > > Do I need some other flags passed to g++ to tell it that I am using a > > fortran created object file? Can I build the fortran file as a > > library? Am I just missing some big step? > > > If you can't tell by now, I am not very familiar with these things, > > unfortunately. > > I think if you use g++ as the driver, you may need to link against > libgfortran. Craig, Thank you! That did it. I updated the example to add a little write statement inside, just to make sure it was working properly. I ended up using the following command line commands to get it working: $ g++ -c invokeF_C.cpp $ gfortran -c invokeF_F.f03 $ g++ -o Invoke_F_with_C_Test invokeF_C.o invokeF_F.o -L /usr/lib - lgfortran $ ./Invoke_F_with_C_Test Results in the following, using the updated files below: > in here. Thank you guys for the help. John N. invokeF_C.cpp **************************************** #include <vector> struct pass{ int lenc; float* c; }; extern "C" void simulation( struct pass* arrays ); int main(){ std::vector< float > cVector(12); pass arrays; arrays.lenc = cVector.size(); arrays.c = &cVector[0]; simulation( &arrays ); } **************************************** invokeF_F.f03 **************************************** subroutine simulation(arrays) bind(c) use iso_c_binding type, bind(c) :: pass integer (c_int) :: lenc type (c_ptr) :: c end type pass type (pass), intent(in) :: arrays real (c_float), pointer :: c_array(:) ! associate c_array with an array allocated in C call c_f_pointer( arrays%c, c_array, (/arrays%lenc/) ) write(*,*) "in here." end subroutine simulation ****************************************
From: Ian Harvey on 9 Apr 2010 19:24 Clarifying what others have posted, the driver for language A needs to be told to pull in the libraries for language B. Perhaps: gfortran -c invokeF_F.f03 g++ -c invokeF_C.cpp g++ invokeF_C.o invokeF_F.o -lgfortran -o my_program_name With this toolset, you could also compile and link all at the same time, here using the gcc driver and specifying both c++ and fortran libraries explicitly: gcc invokeF_C.cpp invokeF_F.f03 -lstdc++ -lgfortran -o my_program_name For more information on what a particular language driver does for you behind the scenes can be observed by adding -v to the command line for the driver. Creating a library (collection of object files) as an intermediate step may be appropriate when you have a larger number of source code files and you want to simplify the specification of all the object files in the linking step. It is not a requirement. IanH
From: glen herrmannsfeldt on 9 Apr 2010 21:23
John N. <ortp21(a)gmail.com> wrote: (snip) > $ g++ -c invokeF_C.cpp > $ gfortran -c invokeF_F.f03 > $ g++ -o Invoke_F_with_C_Test invokeF_C.o invokeF_F.o A better choice is to use gfortran for the link command. gfortran should bring in the Fortran libraries. There is a good chance that those also use the C libraries, where the other way around is less likely. If the Fortran library uses the C library for I/O, it might be possible to do I/O from both Fortran and C. (Even so, if both are buffering things might not come out in the expected order.) -- glen |