- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Below is a simple string sub exposed as a DLL method. Can someone comment on my questions? Thanks!
ARG comes in as a reference to an array of chars due to being passed by reference. Correct?
When I look at ARG's value in VS Watch it looks like an array of chars, not a string: VS Watch shows its type as char[250]* not char[250]. What is the difference and why would there be one at this point inside FORTRAN code?
If I pass a char array longer than 250, will it get truncated to 250 chars or will there be an overflow?
When ARG is assigned to LOCAL, LOCAL get its values, but LOCAL displays as a char[250] not as char[250]*. This I would expect, but I would expect it from ARG too.
But, LOCAL does show as a fixed length char with the usual padding out to 250 chars: it looks fixed length less than 250 chars, no padding. Why is it not padded after being assigned to ARG?
SUBROUTINE MYSUB(ARG)
!DEC$ ATTRIBUTES DLLEXPORT :: MYSUB
!DEC$ ATTRIBUTES ALIAS : 'MYSUB' :: MYSUB
!DEC$ ATTRIBUTES C, REFERENCE
CHARACTER*250 ARG
CHARACTER*250 LOCAL
LOCAL= ARG
RETURN
END
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The ARG will assumed to be a character(len=250) buffer.
Note, Fortran does not use NULL terminated strings.
Your C/C++/C#/?? program will likely pass in a NULL terminated string.
Therefor, you should parse the input (ARG) for NULL,
iNULL = INDEX(ARG, ACHAR(0))
select case(iNULL)
case(0)
LOCAL = ARG ! NULL not found, length of incoming string .ge. buffer
case(1)
LOCAL = ' ' ! NULL string
case default
LOCAL = ARG(1:iNULL-1) ! copy sans NULL, then space fille
end select
If (when) the incoming string is longer than the buffer, data will be truncated (the reference contains the data but it is not accessible beyond the size (len=nn) specified. You can specify ARG with an inordinately large length, or at least 1 larger than your API specifies. Then if NULL not found, you can report string too long.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks so much Jim.
C# client yes. ARG is a char[250] in C#. If I pad in C# ARG to 250 spaces, LOCAL will be padded in FORTRAN. My conclusion is LOCAL=ARG stop at the first NULL it finds in ARG. No need to parse for NULL.
But why does the assignment not pad LOCAL out to 250 regardless as it does if you assign a scaler string to it: LOCAL="Test"
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
program ShowNULL
implicit none
character*250 :: arg
character*250 :: s1
arg = "asdf" ! padds remainder of arg with spaces
print *,len_trim(arg)
arg(50:50) = achar(0) ! inserts NULL at arg(50)
print *,len_trim(arg)
s1 = trim(arg) // "foo"
print *, s1
end program ShowNULL
Output:
4
50
asdf foo
Note, the NULL is treated as non-blank character.
Therefore your statement:
My conclusion is LOCAL=ARG stop at the first NULL it finds in ARG. No need to parse for NULL.
is .FALSE.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If I recall correctly the compilation directive semantics (!DEC$) per Intel Fortran (Digital Fortran previously), you need to specify the REFERENCE attribute explicitly for each received argument of CHARACTER type i.e., ARG in your case. But I may be wrong as I avoid using these directives like the plague, nonetheless I suggest you try out the following:
SUBROUTINE MYSUB(ARG)
!DEC$ ATTRIBUTES DLLEXPORT :: MYSUB
!DEC$ ATTRIBUTES ALIAS : 'MYSUB' :: MYSUB
!DEC$ ATTRIBUTES C, REFERENCE
!DEC$ ATTRIBUTES REFERENCE :: ARG
CHARACTER*250 ARG
CHARACTER*250 LOCAL
LOCAL= ARG
RETURN
END SUBROUTINE
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Separately if you're interested in a standard-based way to interoperate your Fortran code with Microsoft's managed memory .NET system (C#) via the processor that serves as a common companion to both Fortran and .NET i.e., Microsoft C/C++ processor, then see the example below, a recent thread at this forum:
The above example has a C++ caller but that does not matter to the Fortran side of things. The exact same Fortran code can work with a C# caller. And it has a couple of instances of string passing.

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