C strings to Fortran

J

John Smith

Ok, I know this is a common topic, but I didn't find any post that
solves my current problem. I'm using Microsoft Visual C++ 6.0 (SP5),
and Intel Fortran 7.1 Compiler for Windows.

I'm trying to pass a C character string to my Fortran code.
Here is the code (a very simple one):

********** C print.c listing **********
#include <stdio.h>

extern "C" {
void __stdcall PRINT_STRING(char *);
}

int main(void)
{
char *cstring = "Hello World!";
PRINT_STRING(cstring);
return 0;
}


********** Fortran print.f listing **********
subroutine PRINT_STRING(fstring)
CHARACTER*30 fstring
print *,'Fortran string: ',fstring
end
*********************************************

The output is wrong, and I got something like:
" Fortran string: $"
(the '$' may change for any other ascii character)

So, I've tried the hidden-length method, but the linker doesn't like
it:
"test.obj : error LNK2001: unresolved external symbol _PRINT_STRING@8
Debug/test.exe : fatal error LNK1120: 1 unresolved externals"
(I only declare the length parameter into the C listing as written in
some posts here).

If someone got an idea on how to pass those strings, or got a miracle
lib/function to convert those C strings (remember, I use Intel Fortran
Compiler and there is nothing into the documentation that may help
about it...).

I can't neither use CHARACTER*(*) since the Fortran compiler is
complaining about "Error 531 : The variable CSTRING cannot be a value
dummy argument use CHARACTER(*) instead." (even if I use CHARACTER(*)
as written...).

Hey, dudes, help me!
Thanx a lot

Thanks!
 
D

Derk Gwen

(e-mail address removed) (John Smith) wrote:
# Ok, I know this is a common topic, but I didn't find any post that
# solves my current problem. I'm using Microsoft Visual C++ 6.0 (SP5),
# and Intel Fortran 7.1 Compiler for Windows.

That should be detailed in the "Calling Conventions" of the compiler
documentation. If you don't already have the compiler reference guide,
you can try poking around
http://support.intel.com/support/performancetools/fortran/windows/manual.htm
or
http://www.intel.com/software/products/compilers/techtopics/for_prg.htm
for a downloadable copy. Every compiler documentation I have ever seen
has such a section.
 
S

Steve Lionel

Ok, I know this is a common topic, but I didn't find any post that
solves my current problem. I'm using Microsoft Visual C++ 6.0 (SP5),
and Intel Fortran 7.1 Compiler for Windows.

I'm trying to pass a C character string to my Fortran code.
Here is the code (a very simple one):

********** C print.c listing **********
#include <stdio.h>

extern "C" {
void __stdcall PRINT_STRING(char *);
}

int main(void)
{
char *cstring = "Hello World!";
PRINT_STRING(cstring);
return 0;

Replace the above with:

#include <stdio.h>

extern "C" {
void l PRINT_STRING(char *, int slen);
}

int main(void)
{
char *cstring = "Hello World!";
PRINT_STRING(cstring, strlen(cstring));
return 0;

The two changes are:

1: Remove __stdcall - Intel Fortran doesn't use the STDCALL convention by
default.
2. Add the hidden length argument. The hidden length is an int passed by
value after all the arguments.

Note that both of these items are different conventions than Compaq Visual
Fortran uses - CVF does use STDCALL and puts length arguments immediately
after the address. In this example, the latter doesn't matter, but it would
if you passed more than one actual argument.

A good resource for questions such as this is the Intel Fortran/Compaq Visual
Fortran user forum at http://intel.com/IDS/forums/fortran - I invite you to
join the growing and active community there.


Compaq Visual Fortran Support: http://compaq.com/fortran/support/visual.html
Intel Fortran Support: http://developer.intel.com/software/products/support/
Steve Lionel
Software Products Division
Intel Corporation
Nashua, NH

User communities for Intel Fortran and Compaq Visual Fortran:
http://intel.com/IDS/forums/fortran
 
S

Steve Lionel

I'm afraid that no conforming C compiler can silently accept this
gibberish. The first and last line must be conditionally removed when
the code is compiled by a C compiler (the classical #ifdef __cplusplus
stuff) and the l in the function declaration simply makes no sense.

Sorry - the spurious "I" after "void" was a typo and should be removed. You
are also correct that if the file is named with a .c file type, the "C" from
the extern declaration should be removed. If it is .cpp instead, then it is
correct as stated, or one can use the #ifdef as you suggest.



Compaq Visual Fortran Support: http://compaq.com/fortran/support/visual.html
Intel Fortran Support: http://developer.intel.com/software/products/support/
Steve Lionel
Software Products Division
Intel Corporation
Nashua, NH

User communities for Intel Fortran and Compaq Visual Fortran:
http://intel.com/IDS/forums/fortran
 
E

E. Robert Tisdale

John said:
Ok, I know this is a common topic, but I didn't find any post that
solves my current problem. I'm using Microsoft Visual C++ 6.0 (SP5),
and Intel Fortran 7.1 Compiler for Windows.

I'm trying to pass a C character string to my Fortran code.
Here is the code (a very simple one):

/********** C print.c listing **********/
#include <cstdio>
#include <cstring>
extern "C" {
void print_string_(const char *, int);
}

int main(int argc, char* argv[]) {
const
char *cstring = "Hello World!";
print_string_(cstring, strlen(cstring));
return 0;
}


c********** Fortran print.f listing **********
subroutine PRINT_STRING(fstring)
CHARACTER(*) fstring
print *,'Fortran string: ',fstring
end
c*********************************************
 
R

Richard Maine

[about the "hidden" string length argument in many current compilers]
2. Does F2KV address this issue in C-interop?

Yes. F2k (or whatever I have to now call it...apparently F2003,
though that wasn't my choice) addresses this.

The "hidden" arguments are ways of providing information needed to
make assumed-length character dummy arguments work in f77. Because
f77 had no concept of explicit interfaces, the information pretty
much had to be passed for all character arguments. F90/F95/F2whatever
all inherit this for compatibility.

However, it is fundamental to the C interop feature in f2whatever that
the compiler has to know when it is dealing with an interoperable
procedure. This is done by having an explicit interface with the
BIND(C) attribute. If the compiler sees that attribute, it will know
to use an interface appropriate to the C compiler. The low-level
details are technically up to the processor, but in practice none of
the C compilers are likely to have anything like such a hidden
argument, so the compiler won't generate one. In any case,
the implementation has to be compatible with C code that looks
like the specified interface - if there is something "hidden",
then it must be equally hidden from the C code perspective.

Of course, if you want to pass the string length explicitly (as
might be a useful thing to do), then you can do so. But in that
case, there is nothing hidden or otherwise special about it; it
goes wherever you explicitly put it.
 
J

John Smith

Thank you all for your answers.

I've removed the __stdcall statement and put hidden arguments. It
linked but didn't work much.

So I tried to use the "CHARACTER*(*)" statement, and, by renaming my
..for file to .f90, and surprisingly it simply worked :)


But I got another problem right now :)
I have a global C variable (which we will call "foo").
I want to retrieve it into my Fortran Subroutine BAR() without passing
it as an argument.

So I tried to use a COMMON block (my variable is declared in the C
source file as "int foo"). I declared a "COMMON foo" inside the
fortran code, but it doesn't seem to work. I've read that I may use
struct to resolve this but I can't manage to do it :(

Could you help me anymore ?
 
D

Derk Gwen

# So I tried to use a COMMON block (my variable is declared in the C
# source file as "int foo"). I declared a "COMMON foo" inside the
# fortran code, but it doesn't seem to work. I've read that I may use
# struct to resolve this but I can't manage to do it :(

You need to verify this against the documentation, but usually it would be

COMMON /foo/ foo
INTEGER foo

The idea being each C global variable (of whatever type) becomes one
Fortran labelled common block whose variables match C type. However
there is often some name mangling with added or deleted underscores
between C and Fortran external symbols.
 
S

Steve Lionel

1. Do IFC and the future IVF support "after string arg"? Which is the
default?

IFC defaults to "after all args". There is a /Gm switch which provides
compatibility with CVF (and Microsoft Forttran PowerStation) - this changes
the calling mechanism to STDCALL and the string length passing to "after
string". There is no way to separate these.

Intel Visual Fortran will use the same default as IFC, which differs from CVF.
There will be options to get the CVF conventions (with more flexibility.)




Compaq Visual Fortran Support: http://compaq.com/fortran/support/visual.html
Intel Fortran Support: http://developer.intel.com/software/products/support/
Steve Lionel
Software Products Division
Intel Corporation
Nashua, NH

User communities for Intel Fortran and Compaq Visual Fortran:
http://intel.com/IDS/forums/fortran
 
G

Greg Chien

IFC defaults to "after all args". There is a /Gm switch which
provides compatibility with CVF (and Microsoft Forttran
PowerStation) - this changes the calling mechanism to
STDCALL and the string length passing to "after
string". There is no way to separate these.

Would be nicer if the user can have finer control.
Intel Visual Fortran will use the same default as IFC, which
differs from CVF. There will be options to get the CVF
conventions (with more flexibility.)

Sounds better :) Thanks for the explanations.
 
R

Richard Maine

Greg Chien said:
Thanks, Richard. I had to re-read J3/03-007.pdf and I think it is
worthwhile to point out Section 15.2.6, especially the example in NOTE
15.23, for people who would like further reading.

Thanks. (I wrote at least the first draft of that note because I
thought it really needed explaining.)
Am I safe to say that a F200x conforming compiler shall not
expect/generate hidden lengths of strings in the arguments internally when
BIND(C) is specified in a procedure?

Yes. Notice also that you won't be able to have assumed-length
dummies in such a procedure (because they wouldn't work, so the
standard prohibits them in that case).
Well, at least in a practical sense.
I don't think a Fortran compiler writer knows which C compiler their
customers will use,

Mostly it won't matter except in cases where there are C compilers for
the same platform but having interface incompatibilities. I'm told
that some such cases exist and that the vendors will most likely
have compiler switches to indicate which set of C conventions you
need to interoperate with.
nor do I know of any C compiler that produces hidden
length arguments to satisfy Fortran needs.

Me neither.
If the above is true, it is actually a good news to me because the
(implicit) positions of these hidden length arguments always cause
confusions on the C side....

Yes. That's sort of the point of the standard - to facilitate
portability. You can do most of this stuff (C interop) today,
but you have to do different things with different compilers.
Plus, today you sometimes have to be able to write enough C to
write "wrapper" code in C; with the C interop in f2003, it is
hoped that there will be less need to write such C wrappers;
you can tell your Fortran code how to call the C.
 
G

Greg Chien

Yes. Notice also that you won't be able to have assumed-length
dummies in such a procedure (because they wouldn't work, so the
standard prohibits them in that case).

I think it is fair to have such limit, given the complexity from each
language.
Yes. That's sort of the point of the standard - to facilitate
portability. You can do most of this stuff (C interop) today,
but you have to do different things with different compilers.
Plus, today you sometimes have to be able to write enough C to
write "wrapper" code in C; with the C interop in f2003, it is
hoped that there will be less need to write such C wrappers;
you can tell your Fortran code how to call the C.

.... and vice versa, which is mostly what we do.

It is good to have someone (like you) to interpret the standard/draft in
c.l.f. It's hard to notice the hidden string length issue by a glimpse
through 15.2.6.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,280
Latest member
BGBBrock56

Latest Threads

Top