A
Arjan
Hi!
On sister forum Comp.Lang.Fortran I had a discussion about connecting
Proj-4 (a coordinate transformation library, written in C) to my
Fortran project. I do now have a working connection, but it requires
the use of a module named ISO_C_BINDING. This module, which is part of
the F2003 standard, is not supported by the F95 compiler that will
produce our operational executable. Since the people on the Fortran
forum really have done their utmost to help me from their side, I
thought that maybe now you, with your background in C, could give it
the last push it needs.
My C-skills are utterly poor. The last serious code I wrote in C was
only a few hundreds of lines for my MSc thesis in the late 1980s.
My question is: how can I use the Proj-4 library libproj.a from within
my Fortran code, without using module ISO_C_BINDING?
A working C example, named test1.c, is:
----------------------------------------------------------------------------------------------------
#include "proj_api.h"
int p;
main(int argc, char **argv) {
projPJ pj_HIRLAM6, pj_latlong;
double x, y;
if (!(pj_HIRLAM6 = pj_init_plus("+proj=ob_tran +o_proj=eqc
+o_lat_p=30.0 +a=57.29578 +lon_0=0")) )
exit(1);
if (!(pj_latlong = pj_init_plus("+proj=latlong +ellps=clrk66")) )
exit(1);
while (scanf("%lf %lf", &x, &y) == 2) {
x *= DEG_TO_RAD;
y *= DEG_TO_RAD;
p = pj_transform(pj_latlong, pj_HIRLAM6, 1, 0, &x, &y, NULL );
printf("%.2f\t%.2f\n", x, y);
}
exit(0);
}
----------------------------------------------------------------------------------------------------
It compiles with: gcc test1.c -lproj -o test1.exe.
The Fortran sample using ISO_C_BINDING uses a Module named libmyp.f90
for the interfacing between C-library and Fortran-program:
----------------------------------------------------------------------------------------------------
MODULE LibMyP
!
! Module for interfacing between Proj-4 library libproj.a
! and Fortran. So far only pj_init_plus and pj_transform are
supported.
! More routines can be added in a similar way.
! Sample use:
!
! g95 libmyp.f90 testproj.f90 -lproj -o testproj.exe
!
! Formulate your compile statement with care!
! FIRST the sources, THEN the library-path and library!!
!
USE ISO_C_BINDING
IMPLICIT NONE
PRIVATE
PUBLIC :: pj_init_plus, pj_transform
!
INTERFACE
FUNCTION pj_init_plus(name) BIND(C,NAME='pj_init_plus')
USE ISO_C_BINDING
IMPLICIT NONE
TYPE(C_PTR) :: pj_init_plus
CHARACTER(KIND=C_CHAR) :: name(*)
END FUNCTION pj_init_plus
FUNCTION pj_transform(src, dst, point_count, point_offset, &
& x, y, z) BIND(C,NAME='pj_transform')
USE ISO_C_BINDING
IMPLICIT NONE
TYPE(C_PTR), VALUE :: src, dst
INTEGER(C_LONG), VALUE :: point_count
INTEGER(C_INT), VALUE :: point_offset
INTEGER(C_INT) :: pj_transform
REAL(C_DOUBLE) :: x, y, z
END FUNCTION pj_transform
END INTERFACE
!
END MODULE LibMyP
----------------------------------------------------------------------------------------------------
With this Module, the following Fortran sample, named test4.f90, works
with ISO_C_BINDING compatible compilers:
----------------------------------------------------------------------------------------------------
PROGRAM TestProj
!
USE ISO_C_BINDING
USE libmyp
IMPLICIT NONE
!
type(C_PTR) :: SystemInPtr,SystemOutPtr
real(C_DOUBLE) :: x, y, z
INTEGER(C_INT) :: MyResult
!
! Initialize the coordinate systems
!
SystemInPtr = pj_init_plus('+proj=longlat +datum=WGS84 '//&
& '+ellps=WGS84 +towgs84=0,0,0'//char(0))
SystemOutPtr = pj_init_plus('+proj=ob_tran +o_proj=eqc '//&
& '+o_lat_p=30.0 +a=57.29578 +lon_0=0'//char(0))
!
! Read a point in lon-lat [degree], transform to [radians]
!
READ(*,*) x,y
WRITE(*,10) x,y
10 FORMAT('In: ',F15.5,1X,F15.5)
z = 0._C_DOUBLE
x = x * 0.0174533_C_DOUBLE
y = y * 0.0174533_C_DOUBLE
!
! Transform to shifted-pole 60 coordinates
!
MyResult = pj_transform(SystemInPtr,SystemOutPtr, 1, 0, x, y, z)
!
! Show results
!
WRITE(*,20) x,y
20 FORMAT('Out: ',F15.5,1X,F15.5)
!
END PROGRAM TestProj
----------------------------------------------------------------------------------------------------
My next step towards a working executable on our operational system
was to eliminate all references to ISO_C_BINDING.
As collateral damage I have to replace all the C-specific declarations
in my Fortran program to native Fortran types. I don't have a full
grasp of how to do that, but my biggest fear is for the things called
C_PTR. In the C-headerfile, these things live as type projPJ, defined
as follows:
#if !defined(PROJECTS_H)
typedef struct { double u, v; } projUV;
typedef void *projPJ;
#define projXY projUV
#define projLP projUV
#else
typedef PJ *projPJ;
# define projXY XY
# define projLP LP
#endif
I don't even know if the # symbols mean that these lines are comments,
or that they are compiler directives (or anything else).
I know that, during object code generation, Fortran subroutine names
get an underscore appended to distinguish them from C-routines. I
wrote C-wrapper-functions for the two C routines that I would like to
use: pj_init_plus and pj_transform. The C-sample above now also
compiles and runs with function names carrying an extra underscore.
Now I have to re-write the interface module libmyp.f90 and the main
Fortran program test4.f90.
I have no clue of how to proceed.
Can anyone give me a suggestion of the precise syntax for both the
Fortran module and for the main fortran program that would lead to a
working executable that uses the C library?
Thanks!
Arjan
On sister forum Comp.Lang.Fortran I had a discussion about connecting
Proj-4 (a coordinate transformation library, written in C) to my
Fortran project. I do now have a working connection, but it requires
the use of a module named ISO_C_BINDING. This module, which is part of
the F2003 standard, is not supported by the F95 compiler that will
produce our operational executable. Since the people on the Fortran
forum really have done their utmost to help me from their side, I
thought that maybe now you, with your background in C, could give it
the last push it needs.
My C-skills are utterly poor. The last serious code I wrote in C was
only a few hundreds of lines for my MSc thesis in the late 1980s.
My question is: how can I use the Proj-4 library libproj.a from within
my Fortran code, without using module ISO_C_BINDING?
A working C example, named test1.c, is:
----------------------------------------------------------------------------------------------------
#include "proj_api.h"
int p;
main(int argc, char **argv) {
projPJ pj_HIRLAM6, pj_latlong;
double x, y;
if (!(pj_HIRLAM6 = pj_init_plus("+proj=ob_tran +o_proj=eqc
+o_lat_p=30.0 +a=57.29578 +lon_0=0")) )
exit(1);
if (!(pj_latlong = pj_init_plus("+proj=latlong +ellps=clrk66")) )
exit(1);
while (scanf("%lf %lf", &x, &y) == 2) {
x *= DEG_TO_RAD;
y *= DEG_TO_RAD;
p = pj_transform(pj_latlong, pj_HIRLAM6, 1, 0, &x, &y, NULL );
printf("%.2f\t%.2f\n", x, y);
}
exit(0);
}
----------------------------------------------------------------------------------------------------
It compiles with: gcc test1.c -lproj -o test1.exe.
The Fortran sample using ISO_C_BINDING uses a Module named libmyp.f90
for the interfacing between C-library and Fortran-program:
----------------------------------------------------------------------------------------------------
MODULE LibMyP
!
! Module for interfacing between Proj-4 library libproj.a
! and Fortran. So far only pj_init_plus and pj_transform are
supported.
! More routines can be added in a similar way.
! Sample use:
!
! g95 libmyp.f90 testproj.f90 -lproj -o testproj.exe
!
! Formulate your compile statement with care!
! FIRST the sources, THEN the library-path and library!!
!
USE ISO_C_BINDING
IMPLICIT NONE
PRIVATE
PUBLIC :: pj_init_plus, pj_transform
!
INTERFACE
FUNCTION pj_init_plus(name) BIND(C,NAME='pj_init_plus')
USE ISO_C_BINDING
IMPLICIT NONE
TYPE(C_PTR) :: pj_init_plus
CHARACTER(KIND=C_CHAR) :: name(*)
END FUNCTION pj_init_plus
FUNCTION pj_transform(src, dst, point_count, point_offset, &
& x, y, z) BIND(C,NAME='pj_transform')
USE ISO_C_BINDING
IMPLICIT NONE
TYPE(C_PTR), VALUE :: src, dst
INTEGER(C_LONG), VALUE :: point_count
INTEGER(C_INT), VALUE :: point_offset
INTEGER(C_INT) :: pj_transform
REAL(C_DOUBLE) :: x, y, z
END FUNCTION pj_transform
END INTERFACE
!
END MODULE LibMyP
----------------------------------------------------------------------------------------------------
With this Module, the following Fortran sample, named test4.f90, works
with ISO_C_BINDING compatible compilers:
----------------------------------------------------------------------------------------------------
PROGRAM TestProj
!
USE ISO_C_BINDING
USE libmyp
IMPLICIT NONE
!
type(C_PTR) :: SystemInPtr,SystemOutPtr
real(C_DOUBLE) :: x, y, z
INTEGER(C_INT) :: MyResult
!
! Initialize the coordinate systems
!
SystemInPtr = pj_init_plus('+proj=longlat +datum=WGS84 '//&
& '+ellps=WGS84 +towgs84=0,0,0'//char(0))
SystemOutPtr = pj_init_plus('+proj=ob_tran +o_proj=eqc '//&
& '+o_lat_p=30.0 +a=57.29578 +lon_0=0'//char(0))
!
! Read a point in lon-lat [degree], transform to [radians]
!
READ(*,*) x,y
WRITE(*,10) x,y
10 FORMAT('In: ',F15.5,1X,F15.5)
z = 0._C_DOUBLE
x = x * 0.0174533_C_DOUBLE
y = y * 0.0174533_C_DOUBLE
!
! Transform to shifted-pole 60 coordinates
!
MyResult = pj_transform(SystemInPtr,SystemOutPtr, 1, 0, x, y, z)
!
! Show results
!
WRITE(*,20) x,y
20 FORMAT('Out: ',F15.5,1X,F15.5)
!
END PROGRAM TestProj
----------------------------------------------------------------------------------------------------
My next step towards a working executable on our operational system
was to eliminate all references to ISO_C_BINDING.
As collateral damage I have to replace all the C-specific declarations
in my Fortran program to native Fortran types. I don't have a full
grasp of how to do that, but my biggest fear is for the things called
C_PTR. In the C-headerfile, these things live as type projPJ, defined
as follows:
#if !defined(PROJECTS_H)
typedef struct { double u, v; } projUV;
typedef void *projPJ;
#define projXY projUV
#define projLP projUV
#else
typedef PJ *projPJ;
# define projXY XY
# define projLP LP
#endif
I don't even know if the # symbols mean that these lines are comments,
or that they are compiler directives (or anything else).
I know that, during object code generation, Fortran subroutine names
get an underscore appended to distinguish them from C-routines. I
wrote C-wrapper-functions for the two C routines that I would like to
use: pj_init_plus and pj_transform. The C-sample above now also
compiles and runs with function names carrying an extra underscore.
Now I have to re-write the interface module libmyp.f90 and the main
Fortran program test4.f90.
I have no clue of how to proceed.
Can anyone give me a suggestion of the precise syntax for both the
Fortran module and for the main fortran program that would lead to a
working executable that uses the C library?
Thanks!
Arjan