Home > Archive > Fortran > December 2005 > Proper INTERFACE Syntax for CVF6.6 When Using C Subroutines
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Proper INTERFACE Syntax for CVF6.6 When Using C Subroutines
|
|
| tornado Jeff 2005-12-12, 8:17 am |
| All,
Since over at the Intel Fortran support forum, this thread was ignored,
I'll try it here. I am attempting to do some mixed-language programming
(something which I know very little about) and I need some help. Below
is the Fortran routine which calls a C subroutine dec_jpeg2000 and to
make it work properly, I know it needs an INTERFACE section to describe
how the arguments are passed. I don't know what all is required within
the INTERFACE section for this routine because a CHARACTER array
(cpack) is being passed to the subroutine and an INTEGER array is being
returned. If someone could give me some answers as to how the INTERFACE
section is to be constructed, it would be most helpful.
Thanks in advance,
Jeff Krob
FORTRAN ROUTINE -
subroutine jpcunpack(cpack,len,idrstmpl,ndpts,fld)
!$$$ SUBPROGRAM DOCUMENTATION BLOCK
! . . .
! SUBPROGRAM: jpcunpack
! ABSTRACT: This subroutine unpacks a data field that was packed into a
! JPEG2000 code stream
! using info from the GRIB2 Data Representation Template 5.40 or
5.40000.
!
! USAGE: CALL jpcunpack(cpack,len,idrstmpl,ndpts,fld)
! INPUT ARGUMENT LIST:
! cpack - The packed data field (character*1 array)
! len - length of packed field cpack().
! idrstmpl - Contains the array of values for Data ! ! !-
Representation
! Template 5.40 or 5.40000
! ndpts - The number of data values to unpack
!
! OUTPUT ARGUMENT LIST:
! fld() - Contains the unpacked data values
!
! REMARKS: None
!
!$$$
character(len=1),intent(in) :: cpack(len)
integer,intent(in) :: ndpts,len
integer,intent(in) :: idrstmpl(*)
real,intent(out) :: fld(ndpts)
integer :: ifld(ndpts)
integer(4) :: ieee
real :: ref,bscale,dscale
integer :: dec_jpeg2000
INTERFACE
SUBROUTINE dec_jpeg2000(cpack,len,ifld)
!DEC$ ATTRIBUTES C, REFERENCE, ALIAS:'_dec_jpeg2000' :: dec_jpeg2000
! ia32 systems
character(len=1),intent(in) :: cpack(len)
integer :: len
integer :: ifld(ndpts)
END SUBROUTINE dec_jpeg2000
END INTERFACE
ieee = idrstmpl(1)
call rdieee(ieee,ref,1)
bscale = 2.0**real(idrstmpl(2))
dscale = 10.0**real(-idrstmpl(3))
nbits = idrstmpl(4)
!
! if nbits equals 0, we have a constant field where the reference value
! is the data value at each gridpoint
!
if (nbits.ne.0) then
! call gbytes(cpack,ifld,0,nbits,0,ndpts)
! iret=dec_jpeg2000(cpack,len,ifld)
call dec_jpeg2000(cpack,len,ifld)
do j=1,ndpts
fld(j)=((real(ifld(j))*bscale)+ref)*dsca
le
enddo
else
do j=1,ndpts
fld(j)=ref
enddo
endif
return
end
| |
|
| The C signature of dec_jpeg2000 is not clear : is the parameter "len" a
pointer to an integer or the value of an integer ?
If len is declared "int * len;", then your programming is (almost)
right else you should try something like :
call dec_jpeg2000(cpack,%VAL(len),ifld)
In both cases, the interface is not necessary :
- the first case uses the normal F77 argument passing which is the
default in F90
- the second case uses the %VAL function which is not standard (but
very common) and cannot be implemented easily in a F90 interface (we
have to wait for a F2003 compiler)
Moreover, the interface you wrote seems doubtful because the parameter
"ndpts" is not declared
The interface by default is equivalent to :
INTERFACE doc_jpeg2000
SUBROUTINE doc_jpeg2000(cpack,le,ifld)
CHARACTER :: cpack(*)
INTEGER :: len
INTEGER :: ifld(*)
END SUBROUTINE
END INTERFACE
| |
| tornado Jeff 2005-12-12, 7:16 pm |
|
fj wrote:
> The C signature of dec_jpeg2000 is not clear : is the parameter "len" a
> pointer to an integer or the value of an integer ?
>
> If len is declared "int * len;", then your programming is (almost)
> right else you should try something like :
> call dec_jpeg2000(cpack,%VAL(len),ifld)
>
> In both cases, the interface is not necessary :
> - the first case uses the normal F77 argument passing which is the
> default in F90
> - the second case uses the %VAL function which is not standard (but
> very common) and cannot be implemented easily in a F90 interface (we
> have to wait for a F2003 compiler)
>
> Moreover, the interface you wrote seems doubtful because the parameter
> "ndpts" is not declared
>
> The interface by default is equivalent to :
> INTERFACE doc_jpeg2000
> SUBROUTINE doc_jpeg2000(cpack,len,ifld)
> CHARACTER :: cpack(*)
> INTEGER :: len
> INTEGER :: ifld(*)
> END SUBROUTINE
> END INTERFACE
Thanks for the reply. "len", as stated in the documentation, shows the
length of the array "cpack". As for "ndpts", it does not need to be
included in the INTERFACE because it is not passed as an argument to
the C routine doc_jpeg2000. The CVF (Compaq Visual Fortran)
documentation says that when passing arguments from a Fortran routine
to a C routine, there must be an INTERFACE statement to properly define
the arguments. It talks about simple things like an INTEGER type or
REAL type but it does not say anything about CHARACTER arrays from what
I can see. That is why I am searching for help.
Thanks again,
Jeff
| |
| Colin Watters 2005-12-13, 7:04 pm |
| There is a generic problem in passing character arrays/strings between
Fortran and C, this is one reason why an interface block is usually a good
idea. In Intel and Compaq/dec Fortran the !dec$ directive allows the exact
attributes of the C routine and its arguments to be described, and this is
best provided in an interface block along with the rest of the declarations.
The interface in your example *may* be correct, and then again it may not
be. That depends on the code of dec_jpeg2000. Do you have any reference
documentation? or even the source? without either of these, we are all left
guessing.
....Ok having just Googled it I find:
http://oceanlab.rsmas.miami.edu/exp...b/src/grib2lib/
g2clib-1.0.2/dec_jpeg2000.c
which declares it as:
int dec_jpeg2000(char *injpc,g2int bufsize,g2int *outfld)
....if this is what you are trying to use then a closer stab at the interface
block might be:
INTERFACE
integer(2) function dec_jpeg2000(cpack,len,ifld)
!DEC$ ATTRIBUTES C, REFERENCE, ALIAS:'_dec_jpeg2000' :: dec_jpeg2000
!dec$ Attributes VALUE: len
character(len=1), intent(in) :: cpack(len)
integer(2) , intent(in) :: len
integer(2) , intent(out) :: ifld(1)
END function dec_jpeg2000
END INTERFACE
[color=darkred]
Areas of uncertainy include:
1. The declaration of argument LEN. It looks to me like the routine needs
it by value instead of by reference, I'm not certain of the exact form of
the directive required for this, but the above must surely be close
2. There is no way to specify the length of the IFLD array. The routine
seems to assume the caller (i.e. you) will provide an array big enough to
prevent it being over-indexed. I cannot see a way to determine how big this
needs to be. In any case as far as the interface declaration is concerned,
any length will suffice since the rquirement is to declare it an an array
rather than a scalar.
3. The code I found declares arguments 2 and 3 as type 'g2int', which I
guess is equivalent to a 2-byte integer, and thus I hope the integer kind 2
will be correct.
Note that this is a function not a subroutine (C programmers prefer them) so
instead of CALLing it you will need to do something like
integer(2) :: status
| |
| Jugoslav Dujic 2005-12-14, 7:57 am |
| Colin Watters wrote:
| ...Ok having just Googled it I find:
|
| http://oceanlab.rsmas.miami.edu/exp...b/src/grib2lib/
| g2clib-1.0.2/dec_jpeg2000.c
|
| which declares it as:
|
| int dec_jpeg2000(char *injpc,g2int bufsize,g2int *outfld)
|
| ...if this is what you are trying to use then a closer stab at the interface
| block might be:
|
|
| INTERFACE
| integer(2) function dec_jpeg2000(cpack,len,ifld)
| !DEC$ ATTRIBUTES C, REFERENCE, ALIAS:'_dec_jpeg2000' :: dec_jpeg2000
| !dec$ Attributes VALUE: len
| character(len=1), intent(in) :: cpack(len)
| integer(2) , intent(in) :: len
| integer(2) , intent(out) :: ifld(1)
| END function dec_jpeg2000
| END INTERFACE
In addition:
You need
!DEC$ ATTRIBUTES REFERENCE: cpack
Semantics of DEC$REFERENCE attribute is peculiar:
- For a routine, it says that all scalar arguments EXCEPT strings
are passed by reference (arrays are always passed by reference)
- For an individual non-string argument, it specifies the same
- For a string argument, it specifies that the "Fortran-style" hidden
length argument is NOT passed; the "assumed-length" (*) must not
be specified if REFERENCE is specified for a string argument.
Also, depending on what's more suitable, you could use the following
declarations for cpack:
!DEC$ATTRIBUTES REFERENCE:: cpack
character(len=1), intent(in) :: cpack(len)
!DEC$ATTRIBUTES REFERENCE:: cpack
character(len=len), intent(in) :: cpack
integer(1), intent(in) :: cpack(*)
It all depends on how it's easier for you to deal with real argument
corresponding with cpack in Fortran code.
In addition, DEC$ATTRIBUTES C and STDCALL imply VALUE. The ifld argument
should really have (*) instead of 1. So, the alternative spelling could be:
INTERFACE
integer(2) function dec_jpeg2000(cpack,len,ifld)
!DEC$ ATTRIBUTES C, ALIAS:'_dec_jpeg2000' :: dec_jpeg2000
!DEC$ Attributes REFERENCE: cpack
character(len=1), intent(in) :: cpack(len)
integer(2) , intent(in) :: len !VALUE implied by C
integer(2) , intent(out) :: ifld(*) !REFERENCE implied by array
END function dec_jpeg2000
| END INTERFACE
--
Jugoslav
___________
www.xeffort.com
Please reply to the newsgroup.
You can find my real e-mail on my home page above.
| |
| Ken Fairfield 2005-12-14, 9:59 pm |
| James Van Buskirk wrote:
> "Jugoslav Dujic" <jdujic@yahoo.com> wrote in message
> news:40agehF19pcf9U1@individual.net...
>
>
>
>
>
>
>
>
> I'm kinda shocked here, Jugoslav. You seem to be hypnotized by
> the previous poster's mistakes. The return value is specified
> as 'int', so why translate it to 'INTEGER*2', rather than
> 'INTEGER*4' or simply 'INTEGER' ? Also in grib2.h from the
> same folder, we find the declaration:
>
> #ifdef __64BIT__
> typedef int g2int;
> typedef unsigned int g2intu;
> #else
> typedef long g2int;
> typedef unsigned long g2intu;
> #endif
>
> which I (perhaps erroneously) take to mean that the
> g2int arguments are INTEGER*4 as well. Also, the
> 'dec_' prefix to the function name makes me quite
> suspicious: isn't the LEN of a character variable
> following its address as a hidden argument the way
> DEC et seq. compilers passed character arguments by
> default?
Short answer, no. VMS (i.e., "DEC") has always (for the
past 25 years) passed character variables by descriptor
("dope vector" if you will). Now if by "DEC", you mean
"DVF", I'll admit my ignorance and bow out of the discussion
....but DEC means, to me, any of PDP, VAX, or Alpha based
systems (and lately, Itanium as well), running various DEC
provided operating systems. The most familiar of those would
be the one that started life as "VAX/VMS" and uses descriptors
universally.
It just looks to me like the function is
> written to interface with the default DEC calling
> convention.
In this case, I would venture that the prefix "dec_" has
nothing to do with the deceased company once known as DEC.
The only thing you would need, then, is
> to tell the caller the name to send to the linker and
> the TKR (INTEGER*4) of its return value. Or is there
> some other difference (register vs. stack arguments,
> order of arguments pushed on stack, caller or callee
> cleanup of stack) that you are trying to account for
> as well?
-Ken
--
I don't speak for Intel, Intel doesn't speak for me...
Ken Fairfield
D1C Automation VMS System Support
who: kenneth dot h dot fairfield
where: intel dot com
| |
| Jugoslav Dujic 2005-12-15, 3:58 am |
| James Van Buskirk wrote:
| "Jugoslav Dujic" <jdujic@yahoo.com> wrote in message
| news:40agehF19pcf9U1@individual.net...
|
|| Colin Watters wrote:
|
||| int dec_jpeg2000(char *injpc,g2int bufsize,g2int *outfld)
|
|| INTERFACE
|| integer(2) function dec_jpeg2000(cpack,len,ifld)
|| !DEC$ ATTRIBUTES C, ALIAS:'_dec_jpeg2000' :: dec_jpeg2000
|| !DEC$ Attributes REFERENCE: cpack
|| character(len=1), intent(in) :: cpack(len)
|| integer(2) , intent(in) :: len !VALUE implied by C
|| integer(2) , intent(out) :: ifld(*) !REFERENCE implied by array
|| END function dec_jpeg2000
||| END INTERFACE
|
| I'm kinda shocked here, Jugoslav. You seem to be hypnotized by
| the previous poster's mistakes. The return value is specified
| as 'int', so why translate it to 'INTEGER*2', rather than
| 'INTEGER*4' or simply 'INTEGER' ?
In my defense, I must say that I didn't look carefully at all issues;
I focused on REFERENCE/C/ALIAS attributes. I completely missed the
return value.
| Also in grib2.h from the
| same folder, we find the declaration:
|
| #ifdef __64BIT__
| typedef int g2int;
| typedef unsigned int g2intu;
| #else
| typedef long g2int;
| typedef unsigned long g2intu;
| #endif
|
| which I (perhaps erroneously) take to mean that the
| g2int arguments are INTEGER*4 as well. Also, the
| 'dec_' prefix to the function name makes me quite
| suspicious: isn't the LEN of a character variable
| following its address as a hidden argument the way
| DEC et seq. compilers passed character arguments by
| default?
| It just looks to me like the function is
| written to interface with the default DEC calling
| convention.
I don't think so; if the authors were deliberately trying
to mimic CVF calling convention, they would probably uppercase
the name as well. I did glance over the documentation, though,
and it seems that len argument is there because cpack is some
kind of bytestream rather than a "plain vanilla" string; thus,
it isn't expected that it's properly \0 - terminated, but the
stream length must be specified as well.
| The only thing you would need, then, is
| to tell the caller the name to send to the linker and
| the TKR (INTEGER*4) of its return value. Or is there
| some other difference (register vs. stack arguments,
| order of arguments pushed on stack, caller or callee
| cleanup of stack) that you are trying to account for
| as well?
No; I usually don't try to "abuse" the properties of CVF/IVF
default calling convention (even if C routine could match it).
I prefer "straightforward" conversion. (e.g. I'd rather
translate void FOO(char*, int) as
SUBROUTINE FOO(CHARACTER(*)/REFERENCE, INTEGER/VALUE) than
SUBROUTINE FOO(CHARACTER(*)) ).
It ensures portability at least among VF family of compilers.
--
Jugoslav
___________
www.xeffort.com
Please reply to the newsgroup.
You can find my real e-mail on my home page above.
| |
| Jan Vorbrüggen 2005-12-15, 3:58 am |
| > Also, the 'dec_' prefix to the function name makes me quite
> suspicious: isn't the LEN of a character variable
> following its address as a hidden argument the way
> DEC et seq. compilers passed character arguments by
> default?
The "dec" here is short for "decode" or "decoder".
Jan
| |
| James Van Buskirk 2005-12-15, 7:01 pm |
| "Jan Vorbrüggen" <jvorbrueggen-not@mediasec.de> wrote in message
news:40cqlgF19tflsU2@individual.net...
> The "dec" here is short for "decode" or "decoder".
Thank you. I stand corrected.
--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end
| |
| tornado Jeff 2005-12-15, 7:01 pm |
| All,
Thanks for all the help with this situation. I have been away a while
and have not been able to contribute/reply in real time...ish.
To answer some questions, the length of 'ifld(*)' (the decompressed
result of cpack(*) ) is known ahead of time and passed to this
subroutine as the argument 'ndpts'. The compressed Character array
'cpack' with the length of 'len' is passed to subroutine dec_jpeg2000
to be decompressed into the integer array 'ifld(*)' with a known length
of 'ndpts'.
Thanks again for all the help. I'll apply them and see what happens,
Jeff
|
|
|
|
|