Passing a 2 dimensional array from c++ to fortran

S

Sam

Hello all
I have a two dimensional array (the dimensions are not known) that
needs to be passed
to fortran from c++, allocate the dimensions of the array in fortran
code, do some filling up
of the array in fortran and then accessing it in my c++ code.

Say in my c++ code I have;

extern "C" { void foo_(float **, int &, int &); }

int main()
{
............
..............
int rows, columns;
float **array2d; // Now i need to pass this to the fortran code, the
allocation of the array and
// and filling it is done in the fortran code.
// How do i pass this to the fortran subroutine now, i did it this way

foo_(array2d, rows, columns);

// One more question, do i need to do the allocation and stuff here
again
// Do some stuff to manipulate with the array2d

return 0;

}

and my Fortran routine:

subroutine foo(arr,rows,columns)
integer rows, columns
real*8 ,allocatable:: arr :),:)
! do some stuff to allocate the arrray and fil the stuff

end subroutine


Any help would be greatly appreciated

Regards
Sam
 
E

E. Robert Tisdale

Sam said:
I have a two dimensional array (the dimensions are not known)
that needs to be passed to Fortran from C++,
allocate the dimensions of the array in Fortran code,
do some filling up of the array in Fortran and then
accessing it in my C++ code.

Say in my C++ code I have;

extern "C" { void foo_(float **, int&, int&); }

Fortran won't know what to do with an array of pointers to float.
int main(int argc, char* argv[]) {
// ...
// ...
int rows, columns;
float **array2d; // Now I need to pass this to the Fortran code,
// the allocation of the array and filling it
// is done in the Fortran code.
// How do I pass this to the fortran subroutine now, I did it this way

foo_(array2d, rows, columns);

// One more question,
// "Do I need to do the allocation and stuff here again?"
// Do some stuff to manipulate with the array2d.

return 0;
}

and my Fortran routine:

subroutine foo(arr,rows,columns)
integer rows, columns
real*8 ,allocatable:: arr :),:)
! Do some stuff to allocate the arrray and fill the stuff

end subroutine foo


Any help would be greatly appreciated

To do this,
you must pass a Fortran 90 pointer [to a 2D array]
to a Fortran 90 subroutine foo which allocates memory
for the 2D array and assigns a pointer to the array
to the pointer that you passed into subroutine foo.
Your C++ program must include f90_adapter.h
which contains an f90_2DPointer type definition
for a Fortran 90 2D array pointer (for Absoft in this case).
Function main(int, char**) invokes
function f90_2DPointerPointer(const f90_2DPointer*)
to retrieve the pointer to the beginning of the array
from the Fortran 90 pointer object.
> cat foo.f90
subroutine foo(rows, columns, arr)
integer, intent(in):: rows, columns
integer:: row, column
double precision, pointer, dimension:),:):: arr
double precision, pointer, dimension:),:):: tmp
allocate(tmp(rows, columns))
do column = 1, columns
do row = 1, rows
tmp(row, column) = row + 10*column
end do
end do
arr => tmp
end subroutine foo
> f90 -YEXT_NAMES=LCS -YEXT_SFX=_ -c foo.f90
> cat f77_adapter.h
#ifndef guard_f77_adapter_h
#define guard_f77_adapter_h

#include<stdint.h>
#include<stddef.h>
#include<string.h>

/*
* All Fortran 77 type names are of the form:
*
* f77_<type>
*
* where
*
* <type> in {subroutine, character, integer<size>, logical<size>,
* real_4, real_8, single, double, offset, length} and
* <size> in {, _1, _2, _4}.
*
* Note that the <size> parameter includes the empty string.
*/

typedef void f77_subroutine;

typedef char f77_character;

typedef int8_t f77_integer_1;
typedef int16_t f77_integer_2;
typedef int32_t f77_integer_4;
typedef f77_integer_4 f77_integer;

typedef uint8_t f77_logical_1;
typedef uint16_t f77_logical_2;
typedef uint32_t f77_logical_4;
typedef f77_logical_4 f77_logical;

typedef float f77_real_4;
typedef double f77_real_8;
typedef f77_real_4 f77_real;
typedef f77_real_4 f77_single;
typedef f77_real_8 f77_double;

typedef int f77_offset;
typedef size_t f77_length;

#endif/*guard_f77_adapter_h */
> cat f90_adapter.h
#ifndef guard_f90_adapter_h
#define guard_f90_adapter_h

#include<f77_adapter.h>

#ifdef __cplusplus
#define INLINE inline
#define STATIC
#define PRIVATE private:
#define PUBLIC public:
#else /*__cplusplus */
#define INLINE inline
#define STATIC static
#define PRIVATE
#define PUBLIC
#endif/*__cplusplus */

/*
* All Fortran 90 pointer type names are of the form:
*
* f90_<rank><type>Pointer
*
* where
*
* <rank> in {, 1D, 2D, 3D, 4D, 5D, 6D, 7D},
* <type> in {, single, double, integer<size>, logical<size>,
character}
* and
* <size> in {, _1, _2, _3, _4}.
*
* Note that all three parameters include the empty string.
*/

struct f90_Pointer; /* forward declaration */

#ifdef __cplusplus
extern "C" {
INLINE STATIC const
void* f90_PointerPointer(const struct f90_Pointer*);
}
#endif/*__cplusplus */

typedef struct f90_Pointer { /* generic scalar pointer */
PRIVATE
void* P[6];
#ifdef __cplusplus
public:
friend const void* f90_PointerPointer(const struct f90_Pointer*);
#endif/*__cplusplus */
} f90_Pointer;

#ifdef __cplusplus
extern "C" {
#endif/*__cplusplus */
INLINE STATIC const
void* f90_PointerPointer(const f90_Pointer* p) {
return p->P[0]; }
#ifdef __cplusplus
}
#endif/*__cplusplus */

struct f90_triplet; /* forward declaration */

#ifdef __cplusplus
extern "C" {
INLINE STATIC
size_t f90_tripletExtent(const struct f90_triplet*);
INLINE STATIC
ptrdiff_t f90_tripletStride(const struct f90_triplet*);
}
#endif/*__cplusplus */

typedef struct f90_triplet {
PRIVATE
f77_integer lbound;
f77_integer ubound;
f77_integer stride;
#ifdef __cplusplus
public:
friend size_t f90_tripletExtent(const struct f90_triplet*);
friend ptrdiff_t f90_tripletStride(const struct f90_triplet*);
#endif/*__cplusplus */
} f90_triplet;

#ifdef __cplusplus
extern "C" {
#endif/*__cplusplus */
INLINE STATIC
size_t f90_tripletExtent(const f90_triplet* p) {
return (p->lbound < p->ubound)? (p->ubound - p->lbound + 1):
(p->lbound - p->ubound + 1); }

INLINE STATIC
ptrdiff_t f90_tripletStride(const f90_triplet* p) {
return p->stride; }
#ifdef __cplusplus
}
#endif/*__cplusplus */

struct f90_1DPointer; /* forward declaration */

#ifdef __cplusplus
extern "C" {
INLINE STATIC const
void* f90_1DPointerPointer(const struct f90_1DPointer*);
INLINE STATIC
size_t f90_1DPointerExtent1(const struct f90_1DPointer*);
INLINE STATIC
ptrdiff_t f90_1DPointerStride1(const struct f90_1DPointer*);
}
#endif/*__cplusplus */

typedef struct f90_1DPointer { /* generic 1D array pointer */
PRIVATE
void* P[6];
f90_triplet T[1];
#ifdef __cplusplus
public:
friend const void* f90_1DPointerPointer(const struct f90_1DPointer*);
friend size_t f90_1DPointerExtent1(const struct f90_1DPointer*);
friend ptrdiff_t f90_1DPointerStride1(const struct f90_1DPointer*);
#endif/*__cplusplus */
} f90_1DPointer;

#ifdef __cplusplus
extern "C" {
#endif/*__cplusplus */
INLINE STATIC const
void* f90_1DPointerPointer(const f90_1DPointer* p) {
return p->P[0]; }

INLINE STATIC
size_t f90_1DPointerExtent1(const f90_1DPointer* p) {
return f90_tripletExtent(&(p->T[0])); }

INLINE STATIC
ptrdiff_t f90_1DPointerStride1(const f90_1DPointer* p) {
return f90_tripletStride(&(p->T[0])); }
#ifdef __cplusplus
}
#endif/*__cplusplus */

struct f90_2DPointer; /* forward declaration */

#ifdef __cplusplus
extern "C" {
INLINE STATIC const
void* f90_2DPointerPointer(const struct f90_2DPointer*);
INLINE STATIC
size_t f90_2DPointerExtent1(const struct f90_2DPointer*);
INLINE STATIC
ptrdiff_t f90_2DPointerStride1(const struct f90_2DPointer*);
INLINE STATIC
size_t f90_2DPointerExtent2(const struct f90_2DPointer*);
INLINE STATIC
ptrdiff_t f90_2DPointerStride2(const struct f90_2DPointer*);
}
#endif/*__cplusplus */

typedef struct f90_2DPointer { /* generic 2D array pointer */
PRIVATE
void* P[6];
f90_triplet T[2];
#ifdef __cplusplus
public:
friend const void* f90_2DPointerPointer(const struct f90_2DPointer*);
friend size_t f90_2DPointerExtent1(const struct f90_2DPointer*);
friend ptrdiff_t f90_2DPointerStride1(const struct f90_2DPointer*);
friend size_t f90_2DPointerExtent2(const struct f90_2DPointer*);
friend ptrdiff_t f90_2DPointerStride2(const struct f90_2DPointer*);
#endif/*__cplusplus */
} f90_2DPointer;

#ifdef __cplusplus
extern "C" {
#endif/*__cplusplus */
INLINE STATIC const
void* f90_2DPointerPointer(const f90_2DPointer* p) {
return p->P[0]; }

INLINE STATIC
size_t f90_2DPointerExtent1(const f90_2DPointer* p) {
return f90_tripletExtent(&(p->T[0])); }

INLINE STATIC
ptrdiff_t f90_2DPointerStride1(const f90_2DPointer* p) {
return f90_tripletStride(&(p->T[0])); }

INLINE STATIC
size_t f90_2DPointerExtent2(const f90_2DPointer* p) {
return f90_tripletExtent(&(p->T[1])); }

INLINE STATIC
ptrdiff_t f90_2DPointerStride2(const f90_2DPointer* p) {
return f90_tripletStride(&(p->T[1])); }
#ifdef __cplusplus
}
#endif/*__cplusplus */

struct f90_characterPointer; /* forward declaration */

#ifdef __cplusplus
extern "C" {
INLINE STATIC const
char* f90_characterPointerPointer(
const struct f90_characterPointer*);
INLINE STATIC
size_t f90_characterPointerLength(
const struct f90_characterPointer*);
}
#endif/*__cplusplus */

typedef struct f90_characterPointer { /* character string scalar
pointer */
PRIVATE
char* P[6];
#ifdef __cplusplus
public:
friend const char* f90_characterPointerPointer(
const struct f90_characterPointer*);
friend size_t f90_characterPointerLength(
const struct f90_characterPointer*);
#endif/*__cplusplus */
} f90_characterPointer;

#ifdef __cplusplus
extern "C" {
#endif/*__cplusplus */
INLINE STATIC const
char* f90_characterPointerPointer(const f90_characterPointer*
p) {
return p->P[0]; }

INLINE STATIC
size_t f90_characterPointerLength(const f90_characterPointer* p) {
return (size_t)p->P[1]; }
#ifdef __cplusplus
}
#endif/*__cplusplus */

struct f90_1DcharacterPointer; /* forward de3claration */
#ifdef __cplusplus
extern "C" {
INLINE STATIC const
char* f90_1DcharacterPointerPointer(const
f90_1DcharacterPointer*);

INLINE STATIC
size_t f90_1DcharacterPointerExtent1(const
f90_1DcharacterPointer*);

INLINE STATIC
ptrdiff_t f90_1DcharacterPointerStride1(const
f90_1DcharacterPointer*);

INLINE STATIC
size_t f90_1DcharacterPointerLength(const
f90_1DcharacterPointer*);
}
#endif/*__cplusplus */

typedef struct f90_1DcharacterPointer {/* 1D character string array
pointer*/
PRIVATE
char* P[6];
f90_triplet T[1];
#ifdef __cplusplus
public:
friend const char* f90_1DcharacterPointerPointer(
const struct f90_1DcharacterPointer*);
friend size_t f90_1DcharacterPointerExtent1(
const struct f90_1DcharacterPointer*);
friend ptrdiff_t f90_1DcharacterPointerStride1(
const struct f90_1DcharacterPointer*);
friend size_t f90_1DcharacterPointerLength(
const struct f90_1DcharacterPointer*);
#endif/*__cplusplus */
} f90_1DcharacterPointer;

#ifdef __cplusplus
extern "C" {
#endif/*__cplusplus */
INLINE STATIC const
char* f90_1DcharacterPointerPointer(const
f90_1DcharacterPointer* p) { return p->P[0]; }

INLINE STATIC
size_t f90_1DcharacterPointerExtent1(const
f90_1DcharacterPointer* p) { return f90_tripletExtent(&(p->T[0])); }

INLINE STATIC
ptrdiff_t f90_1DcharacterPointerStride1(const
f90_1DcharacterPointer* p) { return f90_tripletStride(&(p->T[0])); }

INLINE STATIC
size_t f90_1DcharacterPointerLength(const
f90_1DcharacterPointer* p) {
return (size_t)p->P[2]; }
#ifdef __cplusplus
}
#endif/*__cplusplus */

#undef PRIVATE
#undef PUBLIC
#undef STATIC
#undef INLINE

#endif/*guard_f90_adapter_h */
> cat main.cc
#include <iostream>
#include <f90_adapter.h>

extern "C" {
f77_subroutine foo_(
const
f77_integer&, // rows
const
f77_integer&, // columns
f90_2DPointer& // 2D array
);
}
int main(int argc, char* argv[]) {
const
f77_integer rows = 3;
const
f77_integer columns = 5;
f90_2DPointer arr;
foo_(columns, rows, arr);
f77_double* A = (f77_double*)f90_2DPointerPointer(&arr);
for (f77_integer row = 0; row < rows; ++row) {
for (f77_integer column = 0; column < columns; ++column) {
std::cout << ' ' << A[row*columns + column];
}
std::cout << std::endl;
}

return 0;
}
> g++ -I. -L/opt/absoft/lib -Wall -ansi -pedantic \
-o main main.cc foo.o -lfio -lf77math
11 12 13 14 15
21 22 23 24 25
31 32 33 34 35
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,534
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top