!DEC$ ATTRIBUTES DECORATE

!DEC$ ATTRIBUTES DECORATE

When I try to use the 'DECORATE' attribute on a mixed-language application I get the following compiler message:

Error: Not a valid attribute for the DEC$ ATTRIBUTES directive. [DECORATE]
!DEC$ ATTRIBUTES DECORATE, STDCALL, ALIAS : 'MODI_GETSTR' :: modi_getstr
-----------------^

The interface used is this (with corresponding C prototype in comments):

!#define modi_getstr MODI_GETSTR
!int4 __stdcall modi_getstr (int4 *str_ptr, char *buffer, int4 *buf_cap);

integer*4 function modi_getstr (
1 str_ptr,
1 buffer,
1 buf_cap)
!DEC$ ATTRIBUTES DECORATE, STDCALL, ALIAS : 'MODI_GETSTR' :: modi_getstr
!DEC$ ATTRIBUTES REFERENCE :: str_ptr, buffer, buf_cap
integer*4 str_ptr, buf_cap
character*(*) buffer
end function modi_getstr

The function is defined in Fortran, and is called both by Fortran and C. What I'm trying to do is retain the case of the external name in uppercase, allow 'decoration', and eliminate the hidden length argument for the character argument. I want the external name to be:

_MODI_GETSTR@12

Does the 'DECORATE' attribute work? What will achieve the desired effect? Is there another way?

7 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Should work - what compiler version?

A couple of things I noticed:

1. Your ATTRIBUTES line is rather long - if you didn't start it in column 1, it would go past column 72 and it would get truncated.

2. The compiler doesn't like CHARACTER*(*) with STDCALL in the routine and REFERENCE in the argument. It's not clear to me why. I'd suggest omitting STDCALL and using VALUE attributes to set the other arguments to VALUE as appropriate.

Steve

Steve - Intel Developer Support

-Should work - what compiler version?

The compiler I'm using is:
Compaq Visual Fortran Standard Edition 6.5.0
Running under Microsoft Windows NT 4.00.1381

-A couple of things I noticed:
-
-1. Your ATTRIBUTES line is rather long - if you didn't start it in column 1, it would go past column 72 and it would get truncated.

I've set the 'Fixed Form Line Length' to 132 in the Fortran Language section of the development environment's 'project settings... fortran' page.

-2. The compiler doesn't like CHARACTER*(*) with STDCALL in the routine and REFERENCE in the argument. It's not clear to me why. I'd suggest omitting STDCALL and using VALUE attributes to set the other arguments to VALUE as appropriate.

I chose to use 'stdcall' because I read that for an argument of type 'string' with the 'reference' option, the 'default' convention would treat the argument as "passed by reference, possibly along with length". Using the 'stdcall' convention would treat the argument as "passed by reference, no length". And the 'stdcall' convention on WNT adds a leading underscore and a trailing number of argument bytes in decoration. (Unfortunately, it also affects the case of externals by converting to lowercase on WNT) I wonder how to interpret the phrase 'possibly along with length' as provided in the table on "Effect of attributes on character strings passed as arguments"? What determines whether a hidden length argument is provided in this case?

Thanks for any light you can shed on this...

Try updating to 6.6B. That version liked your use of DECORATE.

The "possibly" refers to the possible presence or absence of the REFERENCE attribute on the argument itself. The default in CVF is the STDCALL convention (though not with the same attributes as specifying STDCALL!) so leaving out STDCALL will leave the name upcased and decorated as you want (in fact, you can leave out DECORATE, too!). Then you just need to use REFERENCE in both the routine and the argument to get no length.

Steve

Steve - Intel Developer Support

-- Then you just need to use REFERENCE in both the routine and the argument to get no length.

I tried this and can't seem to get it to work: In fact, I created a small testcase that shows that the hidden length argument is still present. (function test_func has two arguments, and the resultant external name is '_TEST_FUNC@12'. I observed this by invoking wordpad on the .obj files.)

Here are the test case source files:

!file interface.inc

interface
integer*4 function test_func (string, string_cap)
!DEC$ATTRIBUTES REFERENCE :: test_func, string, string_cap
character*(*) string
integer*4 string_cap
end function test_func
end interface

!file main.for

program playpen
implicit none
include 'interface.inc'
character*(42) fstring / 'this is a test' /
integer*4 foo
foo = test_func (fstring, 42)
write (6,100) foo
100 format (1x,I)
end

!file test_func.for

integer*4 function test_func (string, string_cap)
implicit none
character*(*) string
integer*4 string_cap
include 'interface.inc'
test_func = 42
return
end

REFERENCE is incompatible with CHARACTER(*) form at least within test_func. I tried few combinations with your code and it seems that:

- With the actual code REFERENCE is ignored for string
- If STDCALL is specified for test_func and REFERENCE is specified for string, the compiler complains that "This passed length character name has been used in an invalid context. [string]"

This is in accordance with Programmer's Guide (page "REFERENCE option for ATTRIBUTES directive"):

If REFERENCE (only) is specified for a character argument, the following occurs:
...
On Windows systems, hidden lengths immediately follow the variable. To get the OpenVMS, Tru64 UNIX, and Linux behavior, use the /iface:nomixed_str_len_arg compiler option.
If REFERENCE is specified for a character argument, and C (or STDCALL) has been specified for the routine, the string is passed with no length. This is true even if REFERENCE is also specified for the routine.

To sum up, to get it working, you need STDCALL for test_func, REFERENCE for string and declaration CHARACTER(some_number) string.

Jugoslav

Jugoslav
www.xeffort.com

...oh, yes, another issue: Have in mind that INTERFACE block has scope of its own. !DEC$ATTRIBUTES refer to the scope they're within - thus !DEC$ATTRIBUTES are not visible outside of INTERFACE block.

To expand, when you "preprocess" your test_func by including contents of "interface.inc" you get:

integer*4 function test_func (string, string_cap)
implicit none
character*(*) string
integer*4 string_cap

  interface
    integer*4 function test_func (string, string_cap)
    !DEC$ATTRIBUTES STDCALL :: test_func
    !DEC$ATTRIBUTES REFERENCE :: string, string_cap
    character*(*) string
    integer*4 string_cap
    end function test_func
  end interface

test_func = 42
return
end 

!DEC$ATTRIBUTES above have meaning only within INTERFACE block -- they don't affect test_func, string and string_cap from outer scope. (The code will produce a link error). You must repeat !DEC$ATTRIBUTES within test_func itself (and you don't need INCLUDE "interface.inc" within test_func).

Jugoslav

Jugoslav
www.xeffort.com

Leave a Comment

Please sign in to add a comment. Not a member? Join today