From: John N. on
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
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
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
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
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