Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29276 Discussions

Passing Characters from C to Intel Fortran

steve_s
Beginner
656 Views
I know this is a very basic questions, but I'm having some issues getting this to work. I have a C program that I wantto call from an Intel V11 fortran program. This program passes a character string and I can't seem to get the Fortran program to retrieve the string. I can pass int and floats with no problem but I just can't get the character data to work. I've looked through the documentation, but I still can't figure it out.

Here is my C program:

extern "C" __declspec( dllexport ) int CTXT(char *tbuf)

{

tbuf = "text string"; // assuming buffer is large enough

return(1);

}


Here is my calling fortran program:

program main

INTERFACE TO INTEGER*4 FUNCTION CTXT(VAR)

CHARACTER*(*) VAR

!DEC$ ATTRIBUTES DLLIMPORT :: CTXT

!DEC$ ATTRIBUTES C, ALIAS:'_CTXT':: CTXT

!DEC$ ATTRIBUTES REFERENCE :: VAR

END

CHARACTER*12 VAR

integer CTXT,i

i=CTXT(VAR)

write(*,*)VAR

end


There character var is blank after it returns from the C routine. I'm not sure what's happening. I would appreciate any help.

0 Kudos
3 Replies
Steven_L_Intel1
Employee
656 Views
There are several problems here, but the fundamental problem is that C does not have string assignment. When you write:

tbuf="text string"

you are assigning the address of the string "text string" to tbuf, overwriting the address Fortran passed in on the stack. This is then discarded. You want to use strcpy (or more reasonably, strncpy) instead.

Second problem (which may or may not be an issue depending on your real application) is that C strings are NUL-terminated, so if you want to find the length of what C wrote you have to use INDEX to look for the NUL.

Third is that you are using 15-year old Microsoft PowerStation syntax to declare the C routine. This will work, but is inappropriate in new code. I suggest instead:

PROGRAM MAIN
USE, INTRINSIC :: ISO_C_BINDING
INTERFACE
FUNCTION CTXT (VAR) BIND (C,NAME='CTXT')
!DEC$ ATTRIBUTES DLLIMPORT :: CTXT ! This is optional
IMPORT
INTEGER(C_INT) :: CTXT
CHARACTER, DIMENSION(*), INTENT(OUT) :: VAR
END FUNCTION CTXT
END INTERFACE

You can then write the rest of the Fortran code the same way, but will want to do something like

ilen = index(VAR,C_NULL_CHAR)-1
write (*,*) VAR(1:ilen)
0 Kudos
mecej4
Honored Contributor III
656 Views
It is an error to assign pointer-type function arguments to addresses of local variables. When the function is exited, the stack is cleaned up and the pointers will have invalid values.
0 Kudos
steve_s
Beginner
656 Views

Thanks, that worked. The reason I'm using the old syntax is because I'm doing this for someone who has an old compiler. I just didn't realize that the address was overwritten by the new address.

Thanks for your help.

0 Kudos
Reply