$ 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
****************************************
> 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 );
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.
> On Apr 9, 2:57ápm, "John N." <ort...@gmail.com> wrote:
>> On Apr 9, 2:27ápm, Tim Prince <tpri...@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!
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.
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
****************************************
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
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