Use of Proj-4 library from Fortran

Hi!

A colleague showed me the Proj-4 library for coordinate transformation. It looked promising, so our systems manager compiled and installed it on our linux box. An example C code shows that indeed a basic transformation is performed allright with the new library.

My current Fortran-90 project, compiled with PGF90, uses a lot of coordinate transformations, so far coded ad hoc my me. I would like to use the routines and functions in libproj.a from within my Fortran code instead to gain accuracy, speed and support for more types of coordinates. I wrote a Module that should handle the interfacing with 2 of the C routines in libproj.a as follows:

MODULE LibMyP
USE ISO_C_BINDING
IMPLICIT NONE
PRIVATE
PUBLIC :: pj_init_plus, pj_transform
!
! Interfacing with C-routines from file “libproj.a”
!
interface
function pj_init_plus(name) bind(C,name=’_pj_init_plus’)
USE ISO_C_BINDING
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
type(c_ptr) src, dst
integer(C_LONG), value :: point_count
integer(C_INT), value :: point_offset
real(C_DOUBLE) x, y, z
end function pj_transform
end interface
!
END MODULE LibMyP


On my Windows box at home this compiles using g95. My sample Fortran main program however does not link using g95. Today at the office, this same code of Module libmyp is not accepted by PGF90. Module ISO_C_BINDING is not found. Apparently the suggestion to use ISO_C_BINDING is not generic.

–> Can you please give a hint of how to use libproj.a in combination with pgf90?

Regards,


Arjan

Hi Arjan,

What version of PGI are you using? ISO_C_BINDING is a F2003 feature which we added (at least most of it) to the 8.0 release. If you are using an earlier version, you will need to upgrade. If you are using 8.0, can you please post the error you’re seeing?

Thanks,
Mat

Hi Mat,

I’m probably (pretty sure) using an older version than 8.x.
What can I do to get this to work with an older version of pgf90?

Arjan

Hi Arjan,

Take a look at Chapter 11 of the PGI User’s Guide. This chapter gives an overview of inter-language calling, including Fortran calling C.

  • Mat

Hi Mat,

I have read the “fine” manual. I stripped the ISO_C_BINDING use-clause and replaced all C-types by what I cound find to be their Fortran equivalent. What I could not figure out is how to declare the stuff that was of TYPE(C_PTR).

With use of ISO_C_BINDING I had:

MODULE LibMyP
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

There were no problems with underscores in object-codes. The ISO_C_BINDING module takes care of that. My Fortran sample program works with the above interfacing Module.

Then I erazed all references to ISO_C_BINDING. From an earlier case I remembered that C-wrapperfunctions with an extra underscore appended to the subroutine names helped connecting the two languages if you tried to do it without the use of ISO_C_BINDING. An example in C showed that my wrapperfunctions are okay. Then the interfacing module. Using the info from chapter 11 in the User Guide, I constructed the following:

MODULE LibMyPo
IMPLICIT NONE
PRIVATE
PUBLIC :: pj_init_plus, pj_transform
!
interface
function pj_init_plus(name)
IMPLICIT NONE
POINTER :: pj_init_plus
character(), intent(in) :: name
end function pj_init_plus


function pj_transform(src,dst,point_count,point_offset,x,y,z)
IMPLICIT NONE
POINTER, INTENT(IN) :: src, dst
integer
8, intent(in) :: point_count
integer, intent(in) :: point_offset
integer :: pj_transform
real*8, INTENT(INOUT) :: x, y, z
end function pj_transform
end interface
!
END MODULE LibMyPo


This does not compile. I feel that I must be nearly there. Only the pointer stuff needs a kick. Can you please give me a hint?

Regards,


Arjan

Hi Arjan,

Well, there really isn’t a good way to do this since F90 Pointers, allocatables, etc. don’t translate well into C due to the use of F90 descriptors. So what you need to do is use an appropriate sized integer (integer in 32-bit, integer*8 in 64-bit) to hold the address of the C pointer and then use Cray pointers to associate the address to the correct data type. Something like:

INTEGER *8 cfunc
INTEGER *8 P
REAL  Q

POINTER(P,Q)
P = CFUNC()
PRINT *, Q

Are you sure you aren’t able to upgrade to 8.0? ISO_C_BINDING would definitely help you.

  • Mat

Thanks Mat, as with the ACCESS=‘TRANSPARENT’ problem from a different discussion, it becomes clear that version 6.1 of pgf90 is maybe a bit old to continue with.

Arjan