1

In C++, I allocate an array of S. In Fortran, I want to access elements of this array. How can I do this?

C++:

struct S {double a; double b;};
S *arrayOfS;
arrayOfS = (S *)new S[123]; // allocate

Fortran 2003:

USE ISO_C_Binding
TYPE, BIND(C) :: SFortran
REAL(c_double) :: a,b
END TYPE SFortran

S and SFortran should now be interoperable, but I also need to have a way to access the elements of the array declared in C++. I'd like to have SC(5)%a in Fortran correspond to arrayOfS[4].a in C++. How do I declare and set the proper value for Fortran array SC that will have this access?

Woody20
  • 791
  • 11
  • 30
  • You don't need to cast the return value of `new` in C++. And while I'm nitpicking, it's idiomatic to put the initializer with the declaration: `S* arrayOfS = new S[123];` instead of on separate lines. – Casey Aug 09 '13 at 20:25
  • 1
    The cast is for clarity. The same line vs separate lines is a "holy war" issue. But this isn't production code, either; it's a simplified example to make the question clear. – Woody20 Aug 09 '13 at 20:57

1 Answers1

3

You could:

1) pass the C++ array to a Fortran BIND(C) procedure that takes an appropriate array argument.

SUBROUTINE proc(array) BIND(C, NAME='proc')
  ...
  TYPE(SFortran) :: array(*)

WIth this approach you might also want to pass the size of the array across and make the array argument explicit shape.

b) have the array pointer as an extern "C" global on the C++ side, and then interoperate through a Fortran module variable with BIND(C).

MODULE some_module
  USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR, C_F_POINTER
  ...
  TYPE(C_PTR), BIND(C, NAME='arrayOfS') :: array_ptr
  ...
  ! In a procedure in the module...
  TYPE(SFortran), POINTER :: array(:)
  CALL C_F_POINTER(array_ptr, array, [123])

Again it might suit to have size of the array available separately to avoid hard coding it in the C_F_POINTER reference.

Which approach is best depends on your requirements!

IanH
  • 21,026
  • 2
  • 37
  • 59
  • Using Intel Fortran compiler XE 12.1.3.300, I get a link error "Undefined external symbol c_f_pointer_set_scalar". The source line that is causing this error is "CALL C_F_POINTER(scPtr, sc, 1)", where scPtr corresponds to your array_ptr, and sc to your 'array'. I cannot find any reference to c_f_pointer_set_scalar, either in Intel's documentation or via Google. Any suggestions? – Woody20 Aug 10 '13 at 07:25
  • 1
    That suggests to me that you didn't include one of the Intel Fortran runtime libraries in the link step. On Windows that procedure is defined in ifmodintr.lib. – IanH Aug 10 '13 at 08:57
  • Right on! Link was using libraries from IVF 11.1.065. I changed this to Composer XE 2011 SP1\Compiler\lib\ia32, and link error is gone. – Woody20 Aug 10 '13 at 18:06