From: John N. on 9 Apr 2010 15:06 I am trying to get a simple example working to invoke a fortran subroutine from C++. I have based my simple example off of the example provided in 14.10 of "fortran 95/2003 explained" by Metcalf, Reid, and Cohen. Their example C code (I am using C++) was incomplete, so I created my own example, as best I could, based on what I thought they were doing. My example .cpp and .f03 files are included at the bottom of the post. They both compile on Linux (ubuntu), using g++ and gfortran, respectively, from the command line using: $ g++ -c invokeF_C.cpp $ gfortran -c invokeF_F.f03 How do I link the two properly in order to create an executable which I can run? I am not very familiar with the command line syntax, so I apologize if this question seems stupid... but I can't find any examples that use iso_c_binding that provide not only a simple example, but also the means to build the solution to run. I think I need to build the fortran file as a library (.a on Linux, but how with fortran?) and then link that library with the .cpp. Thus, I would be building the executable using g++. Would this work? If anyone could provide me with the necessary command line arguments that are needed, I would be most thankful... or, if there are any good examples out there that shed a little more light on a way to properly use iso_c_binding, with a complete example, that would also help out a lot. Thank you. John N. I am using: gcc version 4.3.3 (Ubuntu 4.3.3-5ubuntu4) 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 ****************************************
From: Tim Prince on 9 Apr 2010 15:27 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
From: John N. on 9 Apr 2010 15:57 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 ); } ****************************************
From: John N. on 9 Apr 2010 16:07 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 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.
From: Gordon Sande on 9 Apr 2010 16:20
On 2010-04-09 17:07:42 -0300, "John N." <ortp21(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. |