Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29234 Discussions

Passing dynamic allocated 2D arrays to Fortran subroutine in C++

danielwood
Beginner
686 Views

Hello All,

I tried to pass a dynamic allocated 2D array to a Fortran DLL subroutine in C++.

Please check the following codes. Output on the screen reads like:

4.240000 3.240000 5.240000
4.240000 3.240000 5.240000
4.240000 3.240000 5.240000
4.240000 3.240000 5.240000
4.240000 3.240000 5.240000
4.240000 3.240000 5.240000
4.240000 3.240000 5.240000
4.240000 3.240000 5.240000
6.115449276184175E-307 6.117241938228800E-307 0.000000000000000E+000
0.000000000000000E+000 4.24000000000000 -2.530171125652461E-098
3.897964094641386E-308 2.121995802822848E-314

6.116046830199050E-307 -2.530171125652461E-098 3.897987436627466E-308
2.121995802822848E-314 3.24000000000000 -2.656983832617227E+303
6.115639407007020E-307 -7.845907716021313E+298

6.116644384213925E-307 -2.656983832617227E+303 6.115340629999576E-307
-7.845907716021312E+298 5.24000000000000 0.000000000000000E+000
0.000000000000000E+000 4.24000000000000



It looks like C++ did not pass correct address/values to Fortran.

Please give me some hints and suggestions.

Thank you.

//------------------------------------------------------------------------------------------------------------------------------
/* Main program written in C++ that calls a Fortran routine */
//------------------------------------------------------------------------------------------------------------------------------
#include
#include
#include

#ifdef __cplusplus
extern "C"
#endif

#ifdef USEDLL
__declspec(dllimport)
#endif

void TESTDLL(double **); // Fortran DLL Subroutine

void updateinput(double **);

void main ()
{

//double log_DATA_TEMP[8][3];
double **log_DATA_TEMP;

int i;

log_DATA_TEMP=new double* [8];
for (int i=0; i<8; ++i) {
log_DATA_TEMP=new double [3];
for (int j=0; j<3; ++j) {
log_DATA_TEMP=0.0;
}
}

updateinput(log_DATA_TEMP);

for (i=0;i<8;i++)
{
printf("%lf %lf %lf\\n",log_DATA_TEMP[0],log_DATA_TEMP[1],log_DATA_TEMP[2]);
}

TESTDLL(log_DATA_TEMP);

for(i = 0; i < 8; i++)
delete(log_DATA_TEMP);
delete(log_DATA_TEMP);

}

void updateinput(double **DATA)
{
int i;
for (i=0;i<8;i++)
{
DATA[0]=4.24;
DATA[1]=3.24;
DATA[2]=5.24;
}
}


!---------------------------------------------------------------------------------------------------------------
! TESTDLL.f90
!---------------------------------------------------------------------------------------------------------------
! FUNCTIONS/SUBROUTINES exported from TESTDLL.dll:
subroutine TESTDLL(inputdata)
! Expose subroutine TESTDLL to users of this DLL
!
!DEC$ ATTRIBUTES DLLEXPORT::TESTDLL

Real(8)::inputdata(3,8);
Integer::i
!
Do i=1,3
Write(*,*) inputdata(i,:)
Write(*,*)
Enddo

end subroutine TESTDLL


0 Kudos
2 Replies
IanH
Honored Contributor III
686 Views
You are passing an pointer-to-pointer-to-double (an array of arrays, two levels of indirection) to a fortran function that just expects a pointer-to-double (just one big array, one level of indirection). double[] and double ** aren't the same thing, despite what the syntax might suggest.

Best option if your array is rectangular is to just create one chunk of memory on the C++ side:

[cpp]extern "C" void TESTDLL(double *);
...
double* log_DATA_TEMP = new double [8 * 3];    // in C++ consider using std::vector
...
   log_DATA_TEMP[i*3+j] = some_value;
...
TESTDLL(log_DATA_TEMP);

delete [] log_DATA_TEMP; // note array delete
[/cpp]

Reference the memory on the fortran side as input_data(j,i).

Alternatively, make the fortran handle two levels of indirection:

[fortran]subroutine TESTDLL(input_data) BIND(C, NAME='TESTDLL')  
  USE ISO_C_BINDING, ONLY: C_DOUBLE, C_PTR, C_F_POINTER
  TYPE(C_PTR), INTENT(IN) :: input_data(*)
  REAL(C_DOUBLE), POINTER :: array(:)
...
  DO i = 1, 8
    CALL C_F_POINTER(input_data(i), array, [3])
    DO j = 1, 3
      ! do something with array(j)...
...[/fortran]
This potentially allows you to process "arrays" with varying row lengths.

Apologies if my head C++ compiler/Fortran processor has failed me.
0 Kudos
danielwood
Beginner
686 Views
Hello IanH,

Thank you a lot.

I also did some extra homework here. Thoese two solutions suggested by you should be good approaches.

Thanks again.
0 Kudos
Reply