Question

My data file (thedata.txt) has 10 locations such as:

492484.94 4414814.5
418558.31 4387130.8
488518.45 4425324.5
514821.34 4414303.1
474606.53 4452659.5
488970.51 4462154.6
487880.97 4423944.5
508027.28 4437213.5
492079.38 4429661.5
449220.47 4396761.5

The C file (bidist.c) calculates 10*9/2=45 bilateral distances:

#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void bidist(double thedata[][2], double d2[][1], double ndata[1][1])
{
  register int i,j,k;
  double x,y;
  k=0;
  for(i=0;i<ndata[0][0];i++) {
    for(j=i+1;j<ndata[0][0];j++) {
      x = (thedata[i][0]-thedata[j][0]);
      y = (thedata[i][1]-thedata[j][1]);
      d2[k][0]= (sqrt((x*x)+(y*y)));
      k++;
    }
  }
}

I want to use the "bidist" function to print the "d2" vector in Fortran. I write a Fortran code (main.f90):

program distance
 implicit none
 real, dimension(10,2) :: thedata
 real, dimension(45) :: d2
 integer :: i
 open(10, file='thedata.txt', status='old')
 rewind(10)
 do i=1,10
  read(10,*) thedata(i,1:2)
 end do
 call bidist(thedata,d2,10)
 print*, d2
end program distance

I ran "cl -c bidist.c" and "ifort -c main.f90". Then I did "ifort -o mymain bidist.obj main.obj". But I have the LNK2019 error. How can I fix this problem? Thanks!

Was it helpful?

Solution

I really recommend using iso_c_binding as @haraldkl has pointed out.

After saying this, there seems to be a few mistakes in your code.

1) You define the data and results to be of type real yet the bidist function is expecting doubles.

You might be calling the compiler with different definitions of real and integers, as in I know ifort can take -r8 to say reals are 8-bytes. However I find this can come back to bite you (if you forget to add such flags when using other compilers, etc).

I would either use select_kind or iso_fortran_env or iso_c_binding:

select_kind

integer, parameter                   :: dp = selected_real_kind(15)
real(kind=dp), dimension(10,2)       :: thedata

iso_fortran_env

use, intrinsic                       :: iso_fortran_env
integer, parameter                   :: dp = REAL64
real(kind=dp), dimension(10,2)       :: thedata

iso_c_binding

use, intrinsic                       :: iso_c_binding
real(kind=C_DOUBLE), dimension(10,2) :: thedata

2) The array definitions in bidist define array size in the wrong order. Remember C is row-major.

void bidist(double thedata[][10], double d2[], int ndata)

In this sense I would re-write the program along the following lines:

program distance

        use, intrinsic :: iso_c_binding

        implicit none

        real(kind=C_DOUBLE), dimension(10,2) :: thedata
        real(kind=C_DOUBLE), dimension(45)   :: d
        integer :: i

        interface
            subroutine bidist(d1, d2, n) bind(C)
                import
                real(kind=C_DOUBLE), dimension(10,*), intent(in)    :: d1
                real(kind=C_DOUBLE), dimension(*),    intent(inout) :: d2
                integer(kind=C_INT), value,           intent(in)    :: n
            end subroutine bidist
        end interface

        thedata = 0.0
        d = 0.0
        i = 0

        open(10, file='thedata.txt', status='old')
        rewind(10)
        do i=1,10
                read(10,*) thedata(i,1:2)
        end do

        call bidist(thedata, d, 10)

        do i=1,45
                print*, i, d(i)
        end do
end program distance

And then bidist as:

void bidist(double thedata[][10], double d2[], int ndata)
{
        int i = 0;
        int j = 0;
        int k = 0;
        double x = 0.0;
        double y = 0.0;


        for(i=0;i<ndata;i++) {
                for(j=i+1;j<ndata;j++) {
                        x = (thedata[0][i]-thedata[0][j]);
                        y = (thedata[1][i]-thedata[1][j]);
                        d2[k] = (sqrt((x*x)+(y*y)));
                        k++;
                }
        }

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top