- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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:
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.
Link Copied
3 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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)
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)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page