FORTRAN dynamic arrays used as parameters of functions called from C++ 
Author Message
 FORTRAN dynamic arrays used as parameters of functions called from C++

Hello,

I am attempting to call some fortran functions that are included in
some legacy code necessary to complete this project.  Before anyone
asks, it is not possible to rewrite the code from FORTRAN to C++.

The issue is how FORTRAN handles dynamic arrays.  By dynamic array, I
mean an array where the size of the array is not decided until run
time.  I basically want to create such an array in c++ as a member of
a struct to be sent as a parameter to FORTRAN.  When i send the struct
from C++ to FORTRAN, the size of the item being sent/received is
different.  This is because of FORTRAN's use of what seems to be
called an array descriptor for dynamic arrays.  Below is an Example of
the issue:

     MODULE mExample

      type tX
         Real (Kind=4), dimension(:), pointer :: x     => NULL()
         Integer (Kind=4) ::  nx                       = 0
      end type

      type tY
         type  (tx),dimension(:),pointer :: y => NULL()
         Integer (Kind=4) :: ny                        = 0
      end type

      CONTAINS

!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCc
!
!     A function to delete a set of offsets
!
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
      SUBROUTINE SetNY (tempY, numX)

      ! Implicit none

      IMPLICIT NONE

      type (tY), Intent (IN OUT)      :: tempY
      Integer (KIND=4), Intent (IN), optional :: numX

      tempY%ny = tempY%ny + 3
      PRINT *, 'FORTRAN: setny: tempY%ny = ', tempY%ny ! This is line
31 in Example.f90
       tempY%ny = numX

      RETURN
      END SUBROUTINE

     END MODULE

example.cpp:

#include <iostream>
#include <stdio.h>

using namespace std;

struct tX
{
    float * x;
    int nx;

    tX()
    :
        x(0),
        nx(101)
    {
        // purposefully left empty
    }

Quote:
};

struct tY
{
    tX * y;
    int ny;

    tY()
    :
        y(),
        ny(199634)
    {
         // purposefully left empty
    }

Quote:
};

extern "C" {

    void __mexample__setny
    (
        tY * y,
            int * numX
    );

Quote:
}

int main()
{
    tY yObj;
    int numX = 54;
    //yObj.y->nx = 65;

    cout <<  "C++: Before setny:  yObj.ny = " << yObj.ny << endl;
    __mexample__setny(&yObj, &numX);
    cout <<  "C++: After setny: yObj.ny = " << yObj.ny << endl;

    return 0;

Quote:
}

Using gdb, and printing tempY as soon as it is received in FORTRAN, we
have:


GNU gdb Red Hat Linux (6.5-25.el5rh)
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and
you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for
details.
This GDB was configured as "x86_64-redhat-linux-gnu"...Using host
libthread_db library "/lib64/libthread_db.so.1".

(gdb) break Example.f90:31
Breakpoint 1 at 0x400be9: file Example.f90, line 31.
(gdb) run
Starting program: /home/u43530/fortran/Ex
C++: Before setny: yObj.y.nx = 65, yObj.ny = 101


numx=0x7fff14fc45ec) at Example.f90:31
31            PRINT *, 'FORTRAN: setny: tempY%ny = ', tempY%ny, ',
tempY%y%nx = ', tempY%y%nx
Current language:  auto; currently fortran
(gdb) print tempY
$1 = (REF TO -> ( Type ty
    Type tx
        Type array_descriptor1
PTR TO -> ( VOID ) :: data
int8 :: offset
int8 :: dtype
            Type descriptor_dimension
int8 :: stride
int8 :: lbound
int8 :: ubound
            End Type descriptor_dimension (0:0) :: dim
        End Type array_descriptor1 :: x
int4 :: nx
    End Type tx :: y
int4 :: ny

250286808000, 0})}, 0}, 1180817572}

In case it matters, I am using gfortran as the FORTRAN compiler and g+
+ for C++.  I am operating in redhat enterprise linux version 5.
Also, the current version of gcc installed on the computer is 4.1.2.
However, we are not using this version for compilation of this
program.

The necessary packages were downloaded and extracted into /home/user2/
gccbuild4.3.2/. Then I created gcc-build in /home/user2 and cded to
it. Then used the following commands:

../gccbuild4.3.2/gcc-4.3.2/configure --prefix=/home/user2/gcc-trunk --
enable-languages=c,c++,fortran
make
make install

When compiling with gfortran, the following flags are used:  -g -
frepack-arrays -c -Wa,-64

When compiling with g++, only the -g flag is used.

We are attempting to incorporate the FORTRAN basically as is with
little or no modification to a project in C++.  This is why we are
attempting to simply call these FORTRAN functions from C++.  The
dynamic arrays are defined in the FORTRAN code and we hope to leave
them as they are without modifying the FORTRAN code whatsoever.
Adding additional FORTRAN code is plausible if need be or slightly
modifying the FORTRAN if absolutely need be, but we would like to
minimize the modification of the existing FORTRAN.

Consequently, I can not simply send an empty dynamic array within a
struct from C++ to FORTRAN as well as other parameters and members of
the struct.  After modifying values in FORTRAN to the members of the
"struct" or "type" that includes the dynamic array, these changes are
not replicated correctly upon "return" of the function to C++.  Could
Someone please let me know if this is an issue with gfortran, or
possibly something else.  If this is not an issue, is there an easy
method of doing this, like those found below for non-dynamic arrays.

Basically, I have been able to successfully call numerous functions
originally in FORTRAN from C++, the method of doing this can be found
below.  I have been able to successfully pass simple data types such
as floats or integers to FORTRAN functions (which are marked as  REAL
(KIND=4) and INTEGER (KIND=4) in FORTRAN).  I have also been able to
construct structs of basic types (floats, ints, etc.) in C++ that
correspond to "types" in FORTRAN and send these structs as parameters
to a FORTRAN function where the given parameter is the corresponding
type and things behave as if the parameter was not a struct from c++
but the corresponding type from FORTRAN.  Similarly, nested types
where one FORTRAN type is inside another can be successfully sent by
sending corresponding nested structs.  I have also been able too send
arrays from C++ to FORTRAN perfectly fine.

Below is an example of two FORTRAN types and their corresponding C++
structs:

FORTRAN:
    type A
         Real (Kind=4)     :: a = 0.0
         Real (Kind=4)     :: b = 0.0
         Real (Kind=4)     :: c = 0.0
         LOGICAL (Kind=4)  :: d = .FALSE.
        end type

      type B
         type (A) :: e
         INTEGER (Kind=4)                 :: f = 0
         REAL(Kind=4)                     :: g(73)
         REAL(Kind=4)                     :: h(73)
      end type

C++:

struct A
{
    float a;
    float b;
    float c;
    long int d;

    A()
    :
      a(0.0),
      b(0.0),
      c(0.0),
      d(0)
    {
      // purposefully left empty
    }

Quote:
};

struct B
{
    A e;
    int f;
    float g[73];
    float h[73];

    B()
    :
        e(),
        f(73),
        g(),
        h()
    {
      memset(g, 0, 73);
      memset(h, 0, 73);
    }

Quote:
};

Calling the Fortran Function in File Example.f90:

      SUBROUTINE SetB (z, y, x, v)
      IMPLICIT NONE

!  Declare local variables.

      type (B) z

      INTEGER(4)  ierr

      REAL(4)    y, x, v

       z%e%a  = y
       z%e%b  = x
       z%e%c  = v
       z%e%d  = .FALSE.
       z%f        = 3
       z%g(1)   = -1000.0
       z%g(2)   = 0.0
       z%g(3)   = 1000.0
       z%h(1)   = 0.0
       z%h(2)   = 0.0
       z%h(3)   = 0.0

Can be called from C++ (after using extern "C" to declare the FORTRAN
function as extrnal) as follows:

       extern "C" {

                void __mexample__setb
                (
                      B * z,
                      float * y,
                      float * x,
                      float * v,
                );

       }

**code snippet** (now in main or some other C++ function):

      B z;
      float y = 3.0, x = 4.0, v = 5.0;
      __mexample__setb(&z, &y, &x, &v);



Mon, 20 Jun 2011 01:06:05 GMT  
 FORTRAN dynamic arrays used as parameters of functions called from C++

Quote:

> I am attempting to call some FORTRAN functions that are included in
> some legacy code necessary to complete this project.  Before anyone
> asks, it is not possible to rewrite the code from FORTRAN to C++.

> The issue is how FORTRAN handles dynamic arrays.  By dynamic array, I
> mean an array where the size of the array is not decided until run
> time.  I basically want to create such an array in c++ as a member of
> a struct to be sent as a parameter to FORTRAN.  When i send the struct
> from C++ to FORTRAN, the size of the item being sent/received is
> different.  This is because of FORTRAN's use of what seems to be
> called an array descriptor for dynamic arrays.

This is, unfortunately for your purposes, an implementation detail that
is not covered by the Fortran standard. The use of an array descriptor
of some kind is quite common (perhaps even universal), but it is really
part of a particular Fortran compiler rather than part of the language.
And while I think pretty much all compilers use such a descriptor for a
structure component that is an array pointer, the exact layout of the
descriptor is not so universal. I'm afraid I don't know the layout that
gFortran uses, so I'm not prepared to analyze your particular code.

Even the C interop features of f2003 don't directly cover this case.
There was a proposal to add some specifications that I think are related
to this (I confess to not having studied them in detail) in f2008, but I
think that proposal was pulled from f2008 draft; it might still be in a
separate TR. Even if you did that, it would require modifications to the
Fortran code.

I'd probably recommend that you use the f2003  interop features to do
something close to this. Make the structure component be a C_PTR and use
the C_LOC and C_F_POINTER (spelling?) procedures to convert between it
and a Fortran pointer. If you don't want to touch the "legacy" (I'm
minorly amused by the application of that term to code that uses
features new to f95) Fortran code, you could make a wrapper routine,
which uses the f2003 features and sits between the C++ code and the
legacy Fortran code. That's probably what I'd do.

--
Richard Maine                    | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle           |  -- Mark Twain



Mon, 20 Jun 2011 01:42:27 GMT  
 FORTRAN dynamic arrays used as parameters of functions called from C++

Quote:

> > I am attempting to call some FORTRAN functions that are included in
> > some legacy code necessary to complete this project. ?Before anyone
> > asks, it is not possible to rewrite the code from FORTRAN to C++.

> > The issue is how FORTRAN handles dynamic arrays. ?By dynamic array, I
> > mean an array where the size of the array is not decided until run
> > time. ?I basically want to create such an array in c++ as a member of
> > a struct to be sent as a parameter to FORTRAN. ?When i send the struct
> > from C++ to FORTRAN, the size of the item being sent/received is
> > different. ?This is because of FORTRAN's use of what seems to be
> > called an array descriptor for dynamic arrays.

> This is, unfortunately for your purposes, an implementation detail that
> is not covered by the Fortran standard. The use of an array descriptor
> of some kind is quite common (perhaps even universal), but it is really
> part of a particular Fortran compiler rather than part of the language.
> And while I think pretty much all compilers use such a descriptor for a
> structure component that is an array pointer, the exact layout of the
> descriptor is not so universal. I'm afraid I don't know the layout that
> gFortran uses, so I'm not prepared to analyze your particular code.

> Even the C interop features of f2003 don't directly cover this case.
> There was a proposal to add some specifications that I think are related
> to this (I confess to not having studied them in detail) in f2008, but I
> think that proposal was pulled from f2008 draft; it might still be in a
> separate TR. Even if you did that, it would require modifications to the
> Fortran code.

> I'd probably recommend that you use the f2003 ?interop features to do
> something close to this. Make the structure component be a C_PTR and use
> the C_LOC and C_F_POINTER (spelling?) procedures to convert between it
> and a Fortran pointer. If you don't want to touch the "legacy" (I'm
> minorly amused by the application of that term to code that uses
> features new to f95) Fortran code, you could make a wrapper routine,
> which uses the f2003 features and sits between the C++ code and the
> legacy Fortran code. That's probably what I'd do.

> --
> Richard Maine ? ? ? ? ? ? ? ? ? ?| Good judgment comes from experience;
> email: last name at domain . net | experience comes from bad judgment.
> domain: summertriangle ? ? ? ? ? | ?-- Mark Twain

This is something I had not seen before and appears that it may be
useful to do this.  The issue I am seeing after a small amount of
research is with the fact that the FORTRAN Functions to be called from
C++ are also potentially called from other FORTRAN functions.  It
appears as though making the structure component be a C_PTR will have
ill effects when such a FORTRAN function is being called by another
FORTRAN function.  Is this true or am I misinterpreting the use of
C_PTR, C_LOC and C_F_POINTER?  Also, if this is not an issue, might it
be possible to convert them using the Example.f90 file at the top
presenting the problem so that the correct manner of doing this can be
visualized?

Thank You for your timely and informative response.



Mon, 20 Jun 2011 03:14:02 GMT  
 FORTRAN dynamic arrays used as parameters of functions called from C++

Quote:


> > I'd probably recommend that you use the f2003  interop features to do
> > something close to this. Make the structure component be a C_PTR and use
> > the C_LOC and C_F_POINTER (spelling?) procedures to convert between it
> > and a Fortran pointer. If you don't want to touch the "legacy" (I'm
> > minorly amused by the application of that term to code that uses
> > features new to f95) Fortran code, you could make a wrapper routine,
> > which uses the f2003 features and sits between the C++ code and the
> > legacy Fortran code. That's probably what I'd do.
...
> This is something I had not seen before and appears that it may be
> useful to do this.  The issue I am seeing after a small amount of
> research is with the fact that the FORTRAN Functions to be called from
> C++ are also potentially called from other FORTRAN functions.  It
> appears as though making the structure component be a C_PTR will have
> ill effects when such a FORTRAN function is being called by another
> FORTRAN function.  Is this true or am I misinterpreting the use of
> C_PTR, C_LOC and C_F_POINTER?  Also, if this is not an issue, might it
> be possible to convert them using the Example.f90 file at the top
> presenting the problem so that the correct manner of doing this can be
> visualized?

Well, the Fortran calling routines would have to be correspondingly
modified, so yes, I could see that as an extra nuisance. To me, that
argues for the wrapper approach, having the existing Fortran code call
the existing Fortran routine unmodified, and having the C++ code call
the wrapper. That should achieve your objective of not touching any of
the existing code.

I'll let someone else show an illustrative example. While its a
reasonable request to see one, I'm about ready to get up and go eat
instead of sitting here much longer. If I tried to throw something out
off the top of my head, I'd probably{*filter*}it up. Well..., ok, just a
quick outline, without details (and without checking the syntax either)

  subroutine wrapper(x_c)
    use iso_c_binding

    type, bind(c) :: tx_c
      type(c_ptr) :: x_cptr
      integer :: nx
      ...
    end type
    type tx_f
       real, pointer :: x_fptr(:) => null()
       ...
    end type

    type(tx_c) :: x_c
    type(tx_f) :: x_f

    call c_f_pointer(x_c%x_cptr, x_f%x_fptr, [x_c%nx])
    !--- Copy in any other components as needed.

    call some_fortran_routine(x_f)

    x_c%x_cptr = c_loc(x_f%x_fptr)
    !-- Copy out any other components as needed.
    return
  end

I've shown both copy in and copy out parts. You might not need them both
for every case.

Oh, as an unrelated aside, be aware that your use of kind=4 for integers
and reals is nonportable. The standard does not specify particular kind
values. On the whole, it is probably more portable to just omit the
kind=4 specifier; there are probably more compilers for which omitting
it will give you what you want than there are compilers for which kind=4
will do so. There are several portable ways to get kind values,
including the selected_*_kind intrinsics and, for the C interop, the
kind parameters in iso_c_binding. In any case, even if you just specify
the value 4, I recommend at least putting that specification in a named
constant (aka Fortran parameter) andthen using that constant; that way,
you only need to change it in one place should the need arise.

--
Richard Maine                    | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle           |  -- Mark Twain



Mon, 20 Jun 2011 03:46:07 GMT  
 FORTRAN dynamic arrays used as parameters of functions called from C++

Quote:

> Hello,

> I am attempting to call some FORTRAN functions that are included in
> some legacy code necessary to complete this project.  Before anyone
> asks, it is not possible to rewrite the code from FORTRAN to C++.

> The issue is how FORTRAN handles dynamic arrays.  By dynamic array, I
> mean an array where the size of the array is not decided until run
> time.  I basically want to create such an array in c++ as a member of
> a struct to be sent as a parameter to FORTRAN.  When i send the struct
> from C++ to FORTRAN, the size of the item being sent/received is
> different.  This is because of FORTRAN's use of what seems to be
> called an array descriptor for dynamic arrays.  Below is an Example of
> the issue:

>      MODULE mExample

>       type tX
>          Real (Kind=4), dimension(:), pointer :: x     => NULL()
>          Integer (Kind=4) ::  nx                       = 0
>       end type

>       type tY
>          type  (tx),dimension(:),pointer :: y => NULL()
>          Integer (Kind=4) :: ny                        = 0
>       end type

>       CONTAINS

An alternative might be the clumsier, older, style of

MODULE mExample
  real (kind = 4), dimension(:), allocatable, target:: x

  type tX ...

and later

  allocate(x(1:nx))
  tX%x = x

Then for the C++ side you call with two parameters, the array and the size
of the array. There is no reason that the C++ side cannot also have a
structure that then points to the passed array.



Tue, 21 Jun 2011 21:05:21 GMT  
 FORTRAN dynamic arrays used as parameters of functions called from C++

Quote:

> Hello,

> I am attempting to call some FORTRAN functions that are included in
> some legacy code necessary to complete this project.  Before anyone
> asks, it is not possible to rewrite the code from FORTRAN to C++.

> The issue is how FORTRAN handles dynamic arrays.  By dynamic array, I
> mean an array where the size of the array is not decided until run
> time.  I basically want to create such an array in c++ as a member of
> a struct to be sent as a parameter to FORTRAN.  When i send the struct
> from C++ to FORTRAN, the size of the item being sent/received is
> different.  This is because of FORTRAN's use of what seems to be
> called an array descriptor for dynamic arrays.  Below is an Example of
> the issue:

<snip>

> We are attempting to incorporate the FORTRAN basically as is with
> little or no modification to a project in C++.  This is why we are
> attempting to simply call these FORTRAN functions from C++.  The
> dynamic arrays are defined in the FORTRAN code and we hope to leave
> them as they are without modifying the FORTRAN code whatsoever.
> Adding additional FORTRAN code is plausible if need be or slightly
> modifying the FORTRAN if absolutely need be, but we would like to
> minimize the modification of the existing FORTRAN.

> Consequently, I can not simply send an empty dynamic array within a
> struct from C++ to FORTRAN as well as other parameters and members of
> the struct.  After modifying values in FORTRAN to the members of the
> "struct" or "type" that includes the dynamic array, these changes are
> not replicated correctly upon "return" of the function to C++.  Could
> Someone please let me know if this is an issue with gfortran, or
> possibly something else.  If this is not an issue, is there an easy
> method of doing this, like those found below for non-dynamic arrays.

Matthew,
I wrote a C++ template class (actually, two -- VFArray and VFMatrix)
which emulate most of  F90 semantics -- and are interoperable with --
Fortran 1-d and 2-d arrays. However, that implementation is for Intel
and Compaq Fortran array descriptors, so you will have to tweak the
code.

One description of gfortran array desciptors can be found here:

http://objectmix.com/fortran/381992-call-array-valued-fortran-functio...

I don't know whether they assembled the official documentation in the
meantime. Note that gfortran descriptor is very similar to Compaq one
(class VFArray), so you won't have to work too much to adjust the code.
Unfortunately, the comments are sparse (on my too long TODO-list), but I
hope it's self-documenting enough.

I'll try to attach the code (VFArray.h -- the template classes,
VFArray.cpp -- test case in C++, Foo90.f90 -- Fortran routines of
the test case) in the followup. If it doesn't come through (my
newsserver or newsreader tend to think the files are binary), I'll
send it by e-mail.

--
Jugoslav
www.xeffort.com
Please reply to the newsgroup.
You can find my real e-mail on my home page above.



Fri, 24 Jun 2011 20:43:39 GMT  
 FORTRAN dynamic arrays used as parameters of functions called from C++

Quote:

> Matthew,
> I wrote a C++ template class (actually, two -- VFArray and VFMatrix)
> which emulate most of  F90 semantics -- and are interoperable with --
> Fortran 1-d and 2-d arrays. However, that implementation is for Intel
> and Compaq Fortran array descriptors, so you will have to tweak the
> code.

> One description of gfortran array desciptors can be found here:

> http://objectmix.com/fortran/381992-call-array-valued-fortran-functio...

> I don't know whether they assembled the official documentation in the
> meantime. Note that gfortran descriptor is very similar to Compaq one
> (class VFArray), so you won't have to work too much to adjust the code.
> Unfortunately, the comments are sparse (on my too long TODO-list), but I
> hope it's self-documenting enough.

Be aware that there are plans to change the gfortran descriptor for the
next version (4.5).


Sun, 26 Jun 2011 04:06:24 GMT  
 FORTRAN dynamic arrays used as parameters of functions called from C++

Quote:
> Well, the Fortran calling routines would have to be correspondingly
> modified, so yes, I could see that as an extra nuisance. To me, that
> argues for the wrapper approach, having the existing Fortran code call
> the existing Fortran routine unmodified, and having the C++ code call
> the wrapper. That should achieve your objective of not touching any of
> the existing code.

> I'll let someone else show an illustrative example. While its a
> reasonable request to see one, I'm about ready to get up and go eat
> instead of sitting here much longer. If I tried to throw something out
> off the top of my head, I'd probably{*filter*}it up. Well..., ok, just a
> quick outline, without details (and without checking the syntax either)

> ? subroutine wrapper(x_c)
> ? ? use iso_c_binding

> ? ? type, bind(c) :: tx_c
> ? ? ? type(c_ptr) :: x_cptr
> ? ? ? integer :: nx
> ? ? ? ...
> ? ? end type
> ? ? type tx_f
> ? ? ? ?real, pointer :: x_fptr(:) => null()
> ? ? ? ?...
> ? ? end type

> ? ? type(tx_c) :: x_c
> ? ? type(tx_f) :: x_f

> ? ? call c_f_pointer(x_c%x_cptr, x_f%x_fptr, [x_c%nx])
> ? ? !--- Copy in any other components as needed.

> ? ? call some_fortran_routine(x_f)

> ? ? x_c%x_cptr = c_loc(x_f%x_fptr)
> ? ? !-- Copy out any other components as needed.
> ? ? return
> ? end

> I've shown both copy in and copy out parts. You might not need them both
> for every case.

Richard,
I have spent the last few days amongst other things working on this
suggestion.  Currently it appears as though c_loc is not doing
anything.  Below is my sample code both FORTRAN and C++, as well as
the gdb output:

FORTRAN:

     MODULE mExample

      type tY
         !type  (tx),dimension(:),pointer :: y => NULL()
         !type (tx) :: y
         REAL (KIND=4), dimension(:),pointer :: y_fptr => NULL()
         Integer (Kind=4) :: ny                        = 0
      end type

      CONTAINS

!
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
      SUBROUTINE wrapper(y_c)
      USE iso_c_binding
      type, bind(c) :: ty_c
        type(c_ptr) :: y_cptr
        Integer ny
      end type

      type(ty_c) :: y_c
      type(tY), target :: y_f
      PRINT *, 'FORTRAN: wrapper: y_c%ny = ', y_c%ny!
      call c_f_pointer(y_c%y_cptr, y_f%y_fptr, [y_c%ny])
      PRINT *, 'FORTRAN: wrapper: y_c%ny = ', y_c%ny!
      PRINT *, 'FORTRAN: wrapper: y_f%ny = ', y_f%ny!
      call SetNY(y_f, y_c%ny + 6)

      y_c%y_cptr = c_loc(y_f%y_fptr(1))

      RETURN
      END SUBROUTINE

!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
      SUBROUTINE SetNY (tempY, numY)

      ! Implicit none

      IMPLICIT NONE

      type (tY), Intent (IN OUT)      :: tempY
      Integer (KIND=4), Intent (IN), optional :: numY

      tempY%ny = tempY%ny
      PRINT *, 'FORTRAN: setny: tempY%ny = ', tempY%ny!
       tempY%ny = numY

      RETURN
      END SUBROUTINE

     END MODULE

_______________________________________________________________
C++:

#include <iostream>
#include <stdio.h>

using namespace std;

struct tY
{
    float * y;
    int ny;

    tY()
    :
        y(),
        ny(199634)
    {
         // purposefully left empty
    }

Quote:
};

extern "C" {

    void __mexample_MOD_wrapper
    (
        tY * y,
            int * numY
    );

Quote:
}

int main()
{
    tY yObj;
    int numY = 54;

    cout <<  "C++: Before setny:  yObj.ny = " << yObj.ny << endl;
    __mexample_MOD_wrapper(&yObj, &numY);
    cout <<  "C++: After setny: yObj.ny = " << yObj.ny << endl;

    return 0;

Quote:
}

____________________________________________________________________
gdb (version 4.3.2):


GNU gdb Red Hat Linux (6.5-25.el5rh)
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and
you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for
details.
This GDB was configured as "x86_64-redhat-linux-gnu"...Using host
libthread_db library "/lib64/libthread_db.so.1".

(gdb) break WrapperExample.f90:28
Breakpoint 1 at 0x400d4c: file WrapperExample.f90, line 28.
(gdb) print y_c
No symbol "y_c" in current context.
(gdb) q

GNU gdb Red Hat Linux (6.5-25.el5rh)
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and
you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for
details.
This GDB was configured as "x86_64-redhat-linux-gnu"...Using host
libthread_db library "/lib64/libthread_db.so.1".

(gdb) break WrapperExample.f90:28
Breakpoint 1 at 0x400d4c: file WrapperExample.f90, line 28.
(gdb) run
Starting program: /home/u43530/fortran/a.out
C++: Before setny:  yObj.ny = 199634
 FORTRAN: wrapper: y_c%ny =       199634


28            call c_f_pointer(y_c%y_cptr, y_f%y_fptr, [y_c%ny])
Current language:  auto; currently fortran
(gdb) print y_c
$1 = (REF TO -> ( Type ty_c
PTR TO -> ( VOID ) :: y_cptr
integer(kind=4) :: ny

(gdb) print y_c%y_cptr
$2 = (PTR TO -> ( VOID )) 0x0
(gdb) print y_c%ny
$3 = 199634
(gdb) print y_f
$4 = { (), 0}
(gdb) print y_f%y_fptr
$5 = ()
(gdb) print y_f%ny
$6 = 0
(gdb) print &(y_f)
$7 = (PTR TO -> ( Type ty
    real*4 (0:-1) :: y_fptr
integer(kind=4) :: ny
End Type ty )) 0x7fffa2662ba0
(gdb) print &(y_f%y_fptr)
$8 = (PTR TO -> ( real*4 (0:-1))) 0x7fffa2662ba0
(gdb) print &(y_f%ny)
$9 = (PTR TO -> ( integer(kind=4) )) 0x7fffa2662bd0
(gdb) n
29            PRINT *, 'FORTRAN: wrapper: y_c%ny = ', y_c%ny!
(gdb) print y_f
$10 = { (), 0}
(gdb) print y_f%y_fptr
$11 = ()
(gdb) print y_f%ny
$12 = 0
(gdb) print &(y_f)
$13 = (PTR TO -> ( Type ty
    real*4 (0:-1) :: y_fptr
integer(kind=4) :: ny
End Type ty )) 0x7fffa2662ba0
(gdb) print &(y_f%y_fptr)
$14 = (PTR TO -> ( real*4 (0:-1))) 0x7fffa2662ba0
(gdb) print &(y_f%ny)
$15 = (PTR TO -> ( integer(kind=4) )) 0x7fffa2662bd0
(gdb) q

___________________________________________

If I remove the '(1)' from the line 'y_c%y_cptr = c_loc(y_f%y_fptr
(1))', the compiler experiences a segmentation fault.  Either my
understanding from your example and other examples online is wrong, or
this does not work as expected.  Could you please take a look at this
and inform me what the issue is?



Mon, 27 Jun 2011 00:16:16 GMT  
 FORTRAN dynamic arrays used as parameters of functions called from C++

Quote:

> Currently it appears as though c_loc is not doing
> anything....

"Not doing anything" doesn't makes sense in this context; I'm not sure
what that would mean.

Quote:
> If I remove the '(1)' from the line 'y_c%y_cptr = c_loc(y_f%y_fptr
> (1))', the compiler experiences a segmentation fault.

When you say "the compiler experiences a segmentation fault" do you
actually mean that or do you mean that the compiled program does so when
run? Those are very different things. If the compiler gets a
segmentation fault, then that is a compiler bug. Always. No matter what
the code is.

Quote:
> Could you please take a look at this
> and inform me what the issue is?

Sorry, but I'm not really up to that. Maybe someone else here is. While
it looks to be a nice, small, self-contained sample, and thus ought to
be relatively easy to diagnose, I barely speak C++ at all and also
almost never use de{*filter*}s, so my eyes pretty much glaze over when
looking at this. I don't have the tools handy to work with it directly
myself and remote debugging is always hard. Sometimes I get lucky
inspirations, but one isn't comming to me at the moment.

--
Richard Maine                    | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle           |  -- Mark Twain



Mon, 27 Jun 2011 00:38:03 GMT  
 
 [ 20 post ]  Go to page: [1] [2]

 Relevant Pages 

1. VC++ calling fortran function and fortran function calling a c++ function

2. calling C++ function from Fortran: parameter passing

3. c++ calling fortran and fortran calling C++

4. Memory read problem when calling dynamic arrays in DLL built using VC++ (LabView 5)

5. C++ calling f90 function returning array

6. C++ calling Fortran calling C++

7. Passing C++ array to Fortran function?

8. Mixing C++/Fortran using Two-Dimensional Array

9. How to call C++ function from Fortran 90

10. Calling a fortran function from C++.

11. need to call a C++ function from within a fortran 77 code

12. Call built-in functions of C++ from fortran

 

 
Powered by phpBB® Forum Software