From: bio_amateur on
I just posted this in PGI Forum, yet i hope I can get more help from
the comp.lang.fortran group mems.

I believe that size_t interoperable type in Fortran is
INTEGER(c_size_t). Suppose that I have a C function which accepts an
integer of type size_t.
If this function is called in C code, we can pass an integer constant
or an integer variable of type int without any error.
However, when I call it from Fortran, it doesn't allow me to pass a
variable of type INTEGER, i.e. it requires the variable to be of the
same KIND and TYPE also.

Example: C function:
integer foofunc(size_t abc)


Fortran binding
function foofunc(abc) BIND(C, NAME="foofunc") result (res)
INTEGER(c_size_t), value :: abc
INTEGER(c_int) :: res
end function


Suppose that I already have the variable abc of type INTEGER, if I
pass abc to the function

Code:
INTEGER :: abc
abc = ...
res = foofunc(abc)

I get error
Quote:
GF90-S-0450-Argument number 1 to foofunc: kind mismatch


Is it the only way that I have to create a new variable, say abc_prime
Code:
INTEGER(c_size_t) :: abc_prime
abc_prime = abc
and pass abc_prime to the function.
This is not good if abc is not a scalar but an array. I don't want to
create a duplicate of it. Is there an alternative way that I can do
something in Fortran similar to type cast in C.

Thanks,
Tuan
From: glen herrmannsfeldt on
JB <foo(a)bar.invalid> wrote:
> On 2010-05-26, glen herrmannsfeldt <gah(a)ugcs.caltech.edu> wrote:
>> [Argument passing in C]

>> First, anything smaller than int is always converted to int
>> before the call.

> Really? I wasn't aware of that. Is this something specified in the C
> standard, or is it just implemented this way on some (common?) ABI's?

C89 converts to int very easily. If, for example, you do:
(assuming 8 bit char and 32 bit int)

char a,b,c;
a=b+c;

a and b are converted to int, added, and the result converted
back to char. Of course with twos complement addition and wrap
on overflow you won't notice the difference. Now, if you do:

char b,c;
int a;
a=b+c;

then you can see the difference. As I understand it,
in Fortran if you add INTEGER(C_INT8_T) it can overflow the
eight bits with undefined results. I will guess that either
wrapping or the full sum are possible results.

>> Next, if a prototype is in scope (usually from a #include file)
>> then it will be converted as appropriate.

> Oh, so the above applies only when calling functions without a
> prototype?

Without a prototype, it is passed as int. I believe with
a prototype, after it is converted to int, then it is converted
to the appropriate type. In many cases, to keep the stack properly
aligned an int (usually either 16 or 32 bits) would be pushed
onto the stack. It would then be implementation dependent to
do the final conversion in the caller or callee.

Note in addition, as above expressions involving types smaller
than int are evaluated as int. With char b,c; b+c has type int.
Also, character constants, such as 'x' have type int, not
type char as you might expect.

> I believe C99 made it an error to call a function without a
> prototype. And for good reasons - similar to the use of implicit
> vs. explicit interfaces in Fortran.

I don't know C99 all that well. As with Fortran, I would be
surprised if they invalidate legal C89 programs, but maybe...

> I recall one episode a few years ago when someone (on an internal
> mailing list) got nonsense results when trying to use the C99 round()
> function, which has the prototype

> double round(double x);

> At first the blame was laid on the glibc implementation of round(),
> but the real reason turned out to be that the user hadn't compiled
> with C99 mode, and the prototype for round() is hidden away behind
> some #ifdefs which are set only in C99 mode, and then the compiler
> went and created an implicit prototype

> int rount(int);

It probably has to do that, or it would invalidate legal C89
programs using round as a variable.

> However, the round symbol was still found in the library, so the
> binary linked just fine, but produced nonsense results.

As happens easily if you forget #include <math.h> for any of
the C89 math functions.

> The moral of the story being, explicit interfaces are good, and pay
> attention to the compiler warning and error messages. Both of which
> apply to Fortran as well. :)

(snip)

>> But will there be two copies, one to C_SIZE_T, and then another
>> for the VALUE attribute?

> In principle, but it's entirely possible that the optimizer will be
> able to remove the first one, and construct the typecast variable
> directly on the stack or in some specific register, depending on where
> the ABI requires procedure call arguments to be placed. Assuming that
> the typecast variable is not used after the call, that is.

>> (And especially as C_SIZE_T is the same
>> as C_INT on many C implementations.

> One rather common exception being x86_64, where in all ABI's I'm aware
> of, int is a signed 32-bit integer, and size_t an unsigned 64-bit
> integer.

Well, specifically when compiling in 64 bit mode.

Note that Don Knuth is complaining about the use of 64 bit pointers
in programs that don't need mroe than 4GB. It seems that with
many compilers, you have to use 64 bit mode to use the other
registers now available in x86_64.

Then again, the other question is, when will compilers switch
to using 64 bits for int (or Fortran default INTEGER) type?

-- glen

>

From: bio_amateur on
On May 26, 1:10 pm, glen herrmannsfeldt <g...(a)ugcs.caltech.edu> wrote:
> JB <f...(a)bar.invalid> wrote:
> > On 2010-05-26, glen herrmannsfeldt <g...(a)ugcs.caltech.edu> wrote:
> >> [Argument passing in C]
> >> First, anything smaller than int is always converted to int
> >> before the call.
> > Really? I wasn't aware of that. Is this something specified in the C
> > standard, or is it just implemented this way on some (common?) ABI's?
>
> C89 converts to int very easily.  If, for example, you do:
> (assuming 8 bit char and 32 bit int)
>
>     char a,b,c;
>     a=b+c;
>
> a and b are converted to int, added, and the result converted
> back to char.  Of course with twos complement addition and wrap
> on overflow you won't notice the difference.  Now, if you do:
>
>     char b,c;
>     int a;
>     a=b+c;
>
> then you can see the difference.    As I understand it,
> in Fortran if you add INTEGER(C_INT8_T) it can overflow the
> eight bits with undefined results.  I will guess that either
> wrapping or the full sum are possible results.
>
> >> Next, if a prototype is in scope (usually from a #include file)
> >> then it will be converted as appropriate.
> > Oh, so the above applies only when calling functions without a
> > prototype?
>
> Without a prototype, it is passed as int.  I believe with
> a prototype, after it is converted to int, then it is converted
> to the appropriate type.  In many cases, to keep the stack properly
> aligned an int (usually either 16 or 32 bits) would be pushed
> onto the stack.  It would then be implementation dependent to
> do the final conversion in the caller or callee.
>
> Note in addition, as above expressions involving types smaller
> than int are evaluated as int.  With char b,c; b+c has type int.
> Also, character constants, such as 'x' have type int, not
> type char as you might expect.  
>
> > I believe C99 made it an error to call a function without a
> > prototype. And for good reasons - similar to the use of implicit
> > vs. explicit interfaces in Fortran.
>
> I don't know C99 all that well.  As with Fortran, I would be
> surprised if they invalidate legal C89 programs, but maybe...
>
> > I recall one episode a few years ago when someone (on an internal
> > mailing list) got nonsense results when trying to use the C99 round()
> > function, which has the prototype
> >       double round(double x);
> > At first the blame was laid on the glibc implementation of round(),
> > but the real reason turned out to be that the user hadn't compiled
> > with C99 mode, and the prototype for round() is hidden away behind
> > some #ifdefs which are set only in C99 mode, and then the compiler
> > went and created an implicit prototype
> >     int rount(int);
>
> It probably has to do that, or it would invalidate legal C89
> programs using round as a variable.
>
> > However, the round symbol was still found in the library, so the
> > binary linked just fine, but produced nonsense results.
>
> As happens easily if you forget #include <math.h> for any of
> the C89 math functions.
>
> > The moral of the story being, explicit interfaces are good, and pay
> > attention to the compiler warning and error messages. Both of which
> > apply to Fortran as well. :)
>
> (snip)
>
> >> But will there be two copies, one to C_SIZE_T, and then another
> >> for the VALUE attribute?
> > In principle, but it's entirely possible that the optimizer will be
> > able to remove the first one, and construct the typecast variable
> > directly on the stack or in some specific register, depending on where
> > the ABI requires procedure call arguments to be placed. Assuming that
> > the typecast variable is not used after the call, that is.
> >>  (And especially as C_SIZE_T is the same
> >> as C_INT on many C implementations.
> > One rather common exception being x86_64, where in all ABI's I'm aware
> > of, int is a signed 32-bit integer, and size_t an unsigned 64-bit
> > integer.
>
> Well, specifically when compiling in 64 bit mode.  
>
> Note that Don Knuth is complaining about the use of 64 bit pointers
> in programs that don't need mroe than 4GB.  It seems that with
> many compilers, you have to use 64 bit mode to use the other
> registers now available in x86_64.  
>
> Then again, the other question is, when will compilers switch
> to using 64 bits for int (or Fortran default INTEGER) type?
>
> -- glen
>
>
>
>

Thank you for all the help. So, it's clear to me that using VALUE
means creating a copy on the background.
I just want to make clear that I'm using 64-bit system.
Now, the situation is that I have an array which is quite large, and
passing by reference to the C function. Now, we'll see that creating a
duplicate is not a good choice. So, if we know a way, such as using
pointer to typecast and pass it to the C function. We can get higher
performance.

Thanks
Tuan
From: David Thompson on
On Wed, 26 May 2010 17:10:42 +0000 (UTC), glen herrmannsfeldt
<gah(a)ugcs.caltech.edu> wrote:

> JB <foo(a)bar.invalid> wrote:
> > On 2010-05-26, glen herrmannsfeldt <gah(a)ugcs.caltech.edu> wrote:
> >> [Argument passing in C]
>
> >> First, anything smaller than int is always converted to int
> >> before the call.
>
> > Really? I wasn't aware of that. Is this something specified in the C
> > standard, or is it just implemented this way on some (common?) ABI's?
>
For a C nonprototyped call, or for the variable portion of a varargs
call (since the ellipsis in a prototype doesn't specify types), any
integer type 'narrower' than int is promoted to either signed or
unsigned int, and 'float' (single precision) is converted to double.
This is in the C standard since C89, and common practice before that.
It was *motivated* by the fact many ABIs did, and do, pass anything
smaller as or in a word, and C int is *intended* to match the machine
word though there's no way to actually require that in standardese.

Technically it is legal for a 'narrower' type (fewer value bits) to
occupy more storage because of padding bits, but no one has ever heard
of an example other than the mythical DeathStation 9000.

> >> Next, if a prototype is in scope (usually from a #include file)
> >> then it will be converted as appropriate.
>
> > Oh, so the above applies only when calling functions without a
> > prototype?
>
Right.

> Without a prototype, it is passed as int. I believe with
> a prototype, after it is converted to int, then it is converted
> to the appropriate type. In many cases, to keep the stack properly
> aligned an int (usually either 16 or 32 bits) would be pushed
> onto the stack. It would then be implementation dependent to
> do the final conversion in the caller or callee.
>
Technically not. The standard specifies conversion (directly) to the
parameter=formal=dummy types. But since promotion is (required to be)
value-preserving, AFAICS promoting to int/u-int and then converting to
the target type (always) produces the same result. Even with
prototypes many ABIs pass 'small' arguments in a word, either
zero/sign-extended or with high bits ignored. On the stack or
otherwise in memory this preserves alignment; in register it is
usually just more convenient.

> Note in addition, as above expressions involving types smaller
> than int are evaluated as int. With char b,c; b+c has type int.
> Also, character constants, such as 'x' have type int, not
> type char as you might expect.
>
*Most* expressions; in particular all unary computational operators
apply the 'integer promotions', and most binary operators apply the
'usual arithmetic conversions', which promote both operands
(separately) and then further promote if needed to reach a common
type. The shifts << and >> are an exception; 123 << 1L shifts an int
not a long. The logical operators ! && || use only the nonzeroness of
their operands not the actual value, and ? : the same for its first
operand, and comma doesn't use its first operand's value at all, so
those cases don't promote or convert.

For C++ unlike C, character literals are type char. Other than that,
TTBOMK the *builtin* operators are the same as C, modulo C++98/03
not having the long long and optional other types added in C99.
User-defined overloads are as defined by the user, of course.

> > I believe C99 made it an error to call a function without a
> > prototype. And for good reasons - similar to the use of implicit
> > vs. explicit interfaces in Fortran.
>
No. C99 requires a *declaration*; it no longer allows 'implicit int'
or 'implicit function'. But that declaration can be oldstyle=K&R1 with
unspecified argument types, not a prototype.

Many C programmers -- and courses, tools, etc.-- loosely call any
separate declaration e.g. in a header file a prototype, because the
*benefit* of having such declarations is largely in using prototypes.
But the language doesn't require that.

C++ OTOH has only prototype form (which it doesn't need to call by
that name). And requires declaration of everything always.

> > I recall one episode a few years ago when someone (on an internal
> > mailing list) got nonsense results when trying to use the C99 round()
> > function, which has the prototype
>
> > double round(double x);
>
> > At first the blame was laid on the glibc implementation of round(),
> > but the real reason turned out to be that the user hadn't compiled
> > with C99 mode, and the prototype for round() is hidden away behind
> > some #ifdefs which are set only in C99 mode, and then the compiler
> > went and created an implicit prototype
>
> > int rount(int);
>
Almost; C89 required it to do 'int round ( /* unspecified=K&R1 */ )' .
Depending on the type of the actual, that may be different.
(It's still wrong and likely to malfunction, of course.)