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

how to pass a 2-d vector from VC++ to VF?

angel_c
Beginner
674 Views
Hi. What's the easiest way to pass a 2-d vector from VC++ to VF? I'm aware of the difference in row-column order in VC++ and VF. I also know of passing 1-d vectors from VC++ to VF and was able to do this successfully.

I tried passing a 2-d vector of floats from VC++ to a 2-d array of real*4 in VF but VF didn't retrieve the 2-d array successfully. It was only able to retrieve one element in the 2-d vector. I think it was at (0,2) in VC++ or (1,3) in VF.

Any suggestions?

Thanks,
Angel
0 Kudos
4 Replies
durisinm
Novice
674 Views
Since you are specifying equivalent floating point data types in VC++ and CVF I don't think you have to explicitly do anything special to pass a matrix of values except to exchange the row and column sizes.

This is a simple example. Suppose your 2-d array in VC++ is a 2x3 size:
r1c1 r1c2 r1c3
r2c1 r2c2 r2c3
VC++ is storing them in memory as:
r1c1 r1c2 r1c3 r2c1 r2c2 r2c3
After you pass it to Fortran you should be able to access the values as a transposed 3x2 array with the elements:
r1c1 r2c1
r1c2 r2c2
r1c3 r2c3
Continuing with this same example, you could work with the array in Fortran as a 2x3 if you transpose it in VC++ before passing it to Fortran.

I think I have that straight.

You would have problems if VC++ and CVF are arranging the bits of the floating point values differently. In the example above I'm assuming that the representations are the same.

Mike
0 Kudos
angel_c
Beginner
674 Views
Hi Mike,
here's the code.

-----------------------------------------------------
//C++ code
//Fortran Programs Called By C++
extern "C" {
//function to process meter values
void __stdcall MILLIGAL(int& row, int& col, const double* vCalFile,
int& readingvsize, double* readingvec,
int& metervsize, int* metervec,
char* FNSUM, int num_chars);
}
//Function to pass FLD Data to F90 subroutines for processing
void FldGrav::PassFldGrav(char FNFLD[20], char FNSUM[20], int mark, int nfix,
const std::vector <:VECTOR> >& vCalFile) {
ifstream fldfile(FNFLD, ios::in);
assert(fldfile);

fldfile.seekg(mark);
std::string line;

getline(fldfile, line);

while (getline(fldfile, line)) {
if (!line.empty()) {
stringstream ss(line);
ss>>reading; readingvec.push_back(reading);
ss>>meter; metervec.push_back(meter);
if (ss.fail()) {
meter = 1;
metervec.pop_back();
metervec.push_back(meter);
}
}
}

fldfile.close();

int readingvsize = readingvec.size();
int metervsize = metervec.size();

int row = vCalFile.size();
int col = nmtr_const;
int num_chars = strlen(FNSUM);

//display vectors for testing purposes only
printf("size of vCalFile: %d", row);
for (int i=0; i printf(" ");
for (int j=0; j printf("%f ", vCalFile);
}

MILLIGAL (row, col, &vCalFile[0][0],
readingvsize, &readingvec[0],
metervsize, &metervec[0],
FNSUM, num_chars);

readingvec.clear();
metervec.clear();
D.vCalFile.clear();

}

!F90 Code
subroutine Milligal (col, row, calfilevec, readingvsize, mtrrdg, metervsize, imeter, FNSUM)
implicit none

interface
subroutine ForReading(readingvsize,mtrrdg, FNSUM)
!MS$ATTRIBUTES C,REFERENCE, ALIAS:'_ForReading' :: ForReading
integer readingvsize
real*8 mtrrdg(readingvsize)
character*24 FNSUM

end subroutine ForReading
end interface

character*24 FNSUM
integer calmtrvsize, readingvsize, metervsize
integer i, j, col, row, textlen
integer imeter(metervsize)
real*8 calfilevec(row, col), mtrrdg(readingvsize)

write(*,*) row, col
write(*,*)
write(*,*) calfilevec(1,1)
write(*,*) calfilevec(2,1)
write(*,*) calfilevec(3,1)
write(*,*) calfilevec(1,2)
write(*,*) calfilevec(2,2)
write(*,*) calfilevec(3,2)
write(*,*)
write(*,*)

do i = 1,row
do j = 1, col
write(*,*) i, j, calfilevec(i,j)
end do
end do


textlen = len(FNSUM)
FNSUM(textlen:textlen) = char(0)

call ForReading(readingvsize, mtrrdg, FNSUM)
return
end subroutine Milligal
---------------------------------------------------

That's the C++ and Fortran code I wrote for transferring 2D vectors from C++ to Fortran. And it's not working, Fortran only retrieves the 1st row of the 2D vector from C++, but not the 2nd row.

I'm, stuck in this problem for 2 days now. It's getting more and more frustrating. I really hope you can help me out. I wrote another code that does the same thing except that I used arrays instead of vectors but I get the same problem. I really wanted to use vectors instead of arrays, I just tried out using arrays in this case, but to no avail.

Thanks,
Angel
0 Kudos
tol1
Beginner
674 Views
Here is a sample of VC++ calling F95 (the compiler I used was from Lahey, but you should be able to change the pragma for Intel fortran.) I have not tried using vector from the standard library, but I think it should be similar.

! fortran 95 suboutine to be call by MSVC
subroutine sub1(dummy1,dummy2,array1,array2,m,n,fname)
DLL_EXPORT sub1
INTEGER,INTENT(IN) :: m,n
REAL(KIND=8) :: dummy1,dummy2
REAL(KIND=4),DIMENSION(m) :: array1
REAL(KIND=4),DIMENSION(m,n) :: array2
CHARACTER(LEN=80) :: fname
REAL(KIND=16) quad1,quad2
INTEGER :: i,j
quad1 = dummy1**20
quad2 = dummy2**20
PRINT *, "dummy1 = ",dummy1,", dummy2 = ",dummy2
PRINT *, dummy1**20,dummy2**20
dummy1 = dummy1**20; dummy2 = dummy2**20
PRINT *, dummy1,dummy2
PRINT *, "quad1 = ",quad1,", quad2 = ",quad2
PRINT '(8f10.4)',array1
PRINT *,"printing array 2"
PRINT '(f10.4)',((array2(i,j),i=1,m),j=1,n)
!PRINT *, array2
PRINT *, "Fortran 95 array2(3,4) = ", array2(3,4)
PRINT *, "Fortran 95 array2(6,2) = ", array2(6,2)
PRINT *, fname,LEN(fname)
fname = fname // " back from fortran 95"
end

#include
#include

// extern "C" void _stdcall sub1(double*,double*,float[],float[][5]);
extern "C" void _stdcall sub1(double *,double*, float*,float[10][5]);
using namespace std;

void main(void)
{
double ftemp1,ftemp2;
float array1[10];
float array2[10][5];
ftemp1 = 23.4;
ftemp2 = 45.2;
for(int i=0;i<10;i++)
array1 = float(i);
for(int i=0;i<10;i++)
for(int j=0;j<5;j++)
array2 = float(i+j);
sub1(&ftemp1,&ftemp2,array1,array2);
cout << endl;
cout << "ftemp1 =" << ftemp1 << endl;
cout << "ftemp2 =" << ftemp2 << endl;
cout << "done!" << endl;
}

Good Luck!

Long
0 Kudos
Jugoslav_Dujic
Valued Contributor II
674 Views
Angel, could you reduce the sample to a small compilable workspace and attach it (zipped) (C file with a main(), and input file). It's hard to find out what's going on without debugger, and I'm not competent enough with STL to boil it down myself.

Jugosllav
0 Kudos
Reply