- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have c libraries that unpack GRIB2 data that I receive from NCEP/NWS. The data looks correct INSIDE my c routines, but I am at a loss to accessing the c structure from fortran. The c library creates and dynamically allocates the a structure called 'gribfield' as follows:
struct
gribfield {g2int version,discipline;
g2int *idsect;
g2int idsectlen;
unsigned char *local;g2int locallen;
g2int ifldnum;
g2int griddef,ngrdpts;
g2int numoct_opt,interp_opt,num_opt;
g2int *list_opt;
g2int igdtnum,igdtlen;
g2int *igdtmpl;
g2int ipdtnum,ipdtlen;
g2int *ipdtmpl;
g2int num_coord;
g2float *coord_list;
g2int ndpts,idrtnum,idrtlen;
g2int *idrtmpl;
g2int unpacked;
g2int expanded;
g2int ibmap;
g2int *bmap;
g2float *fld;
};
typedef
struct gribfield gribfield;The C routine I call simply returns a pointer to this structure as follows:
g2int g2_getfld(
unsigned char *cgrib,g2int ifldnum,g2int unpack,g2int expand,gribfield **gfld)
I have tried everything trying to access this data from IVF 10.025 with no luck. My interface code is as follows:
interface function g2_getfld (mgrib,ifldnum,unpack,expand,gfld) !DEC$ ATTRIBUTES C, DECORATE, ALIAS:'g2_getfld' :: g2_getfld integer (kind=int_ptr_kind()) gfld type gribfield sequence integer*4 version integer*4 discipline integer*4, allocatable :: idsect(:) integer*4 idsectlen character, allocatable :: local(:) integer*4 locallen integer*4 ifldnum integer*4 griddef,ngrdpts integer*4 numoct_opt,interp_opt,num_opt integer*4, allocatable :: list_opt(:) integer*4 igdtnum,igdtlen integer*4, allocatable :: igdtmpl(:) integer*4 ipdtnum,ipdtlen integer*4, allocatable :: ipdtmpl(:) integer*4 num_coord real, allocatable :: coord_list(:) integer*4 ndpts,idrtnum,idrtlen integer*4, allocatable :: idrtmpl(:) integer*4 unpacked integer*4 expanded integer*4 ibmap integer*4, allocatable :: bmap(:) real, allocatable :: fld2(:) end type pointer (gfld, version) character*1 mgrib(131040) integer*4 ifldnum,unpack,expand end function g2_getfld end interfaceHow can I access the data from the gribfield structure in Fortran? For example, I want to print the parameter 'version'?
Thanks for any help you can provide!
Brett A. Wilt
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
* Integer (or Cray) pointers on Fortran side, or, better
* ISO_C_BINDING module
The former is a non-standard (but common) extension. The latter is the new standard, so I recommend its use:
In short, each g2int* member will map to a TYPE(C_PTR) in Fortran. To dereference it into an array, you have to use a temporary POINTER array:
integer, pointer:: pidsect(:)
...
call C_F_POINTER(gfld%idsect, pidsect, (/idsectlen/) )
write(*,*) pidsect(1)In the spirit of ISO_C_BINDING, you may also want to change !DEC$ATTRIBUTES into BIND(C, NAME="g2_getfld"). Don't forget to USE, INTRINSIC:: ISO_C_BINDING on the relevant places.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for the reply!
Do I use the type structure 'gribfield' in my fortran INTERFACE code to match the c structure? Is my code correct for this or do I not use the TYPE structure along with the allocatable array declarations?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
INTERFACE is somewhat peculiar in Fortran, as the declaration of TYPE gribfiled will not be "visible" outside the INTERFACE (unless there's IMPORT statement supported in IVF10 -- I didn't check -- or the SEQUENCE attribute in both type definitions). Instead, it's best that you write it like this:
MODULE m_gribfield
USE, INTRINSIC:: ISO_C_BINDING
INTEGER, PARAMETER:: g2int =4
TYPE gribfield
INTEGER(g2int):: version, discipline
TYPE(C_PTR):: idsect
INTEGER(g2int):: idsectlen
...
END TYPE gribfield
END MODULE m_gribfield
INTERFACE
function g2_getfld (mgrib,ifldnum,unpack,expand,gfld) bind(C, NAME="g2_getfld")
USE m_gribfield
INTEGER(g2int):: g2_getfld
INTEGER(g2int), VALUE:: ifldnum
INTEGER(g2int), VALUE:: unpack
INTEGER(g2int), VALUE:: expand
TYPE(C_PTR):: gfld
END FUNCTION
END INTERFACE
TYPE(g2_getfld), POINTER:: gfld
TYPE(C_PTR):: p_gfld
...
iret = g2_getfld(...p_gfld)
CALL C_F_POINTER(p_gfld, gfld)
I'm not positive what is mgrib/cgrib, so I left it untranslated -- you may wish to retain the character, or do it through type(C_PTR) as well.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ireally appreciate your time and help with this. I am notextensively familiar with c, so this is learning for me. Here is where I am now:
module m_gribfield use, intrinsic:: iso_c_binding integer, parameter:: g2int=4 type gribfield integer(g2int):: version integer(g2int):: discipline type(c_ptr):: idsect integer(g2int):: idsectlen type(c_ptr):: local integer(g2int):: locallen integer(g2int):: ifldnum integer(g2int):: griddef integer(g2int):: ngrdpts integer(g2int):: numoct_opt integer(g2int):: interp_opt integer(g2int):: num_opt type(c_ptr):: list_opt integer(g2int):: igdtnum integer(g2int):: igdtlen type(c_ptr):: igdtmpl integer(g2int):: ipdtnum integer(g 2int):: ipdtlen type(c_ptr):: ipdtmpl integer(g2int):: num_coord type(c_ptr):: coord_list integer(g2int):: ndpts integer(g2int):: idrtnum integer(g2int):: idrtlen type(c_ptr):: idrtmpl integer(g2int):: unpacked integer(g2int):: expanded integer(g2int):: ibmap type(c_ptr):: bmap type(c_ptr):: fld2 end type gribfield end module m_gribfieldsubroutine readgrib
use m_gribfield use, intrinsic:: iso_c_bindingtype
(g2_getfld), pointer:: gfldtype
(c_ptr):: p_gfld interface function g2_getfld (mgrib,ifldnum,unpack,expand,gfld) !dec$ attributes c, decorate, alias:'g2_getfld' :: g2_getfld use m_gribfield character*1 mgrib(131040) integer(g2int):: g2_getfld integer(g2int), value:: ifldnum integer(g2int), value:: unpack integer(g2int), value:: expand type(c_ptr):: gfld end function g2_getfld end interface ierr=g2_getfld(%ref(mgrib),1,1,0,%ref(gfld)) call c_f_pointer(p_gfld, gfld) print*,gfld%versionreturn
end
Here are my compiler error messages:
Error1 Error: This is not a derived type name. [G2_GETFLD]C:DevelopmentModel_x32_VS2005Sourcegribread.f1370
This occurs when the line
type(g2_getfld), pointer:: gfld
is added to the subroutione as indicated above.
Error2 Error: This variable or component must be of a derived or structure type [GFLD]C:DevelopmentModel_x32_VS2005Sourcegribread.f1476
Error3 Error: This is not a field name that is defined in the encompassing structure. [VERSION]C:DevelopmentModel_x32_VS2005Sourcegribread.f1476
These occur when I try and print the value of version with:
print*,gfld%version
Can you show me how to print the value of version? Is it incorrect above?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What if you BIND(C,NAME="g2_getfld" )? but keep the !DEC$ meta command as it acts as a workaround for the compiler's failure to prepend a _ to the symbol.
Gerry
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Your ATTRIBUTES line looks fine to me as it is.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
He could throw out the Alias and retain the Decorate and all would be fine unless Decorate's behavior changes in the future. Now you know why the HP guy suggestedthat one needs to experiment from release to release.
Gerry
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page