- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am trying to implement writing to a named pipe with a USEROPEN function (written in Fortran). when the useropen function is called, the FILENAME is "Undefined Address". If I simply hard-code the pipe name everything works as expected, but obviously that not going to work for production. Here's my code. I am a Fortran newb, so please don't hesitate to critique any part of this.
module fortranpipe
implicit none
contains
subroutine writetopipe()
!dec$ attributes dllexport :: writetopipe
!dec$ attributes alias : "writetopipe" :: writetopipe
implicit none
integer*4 :: i
OPEN(UNIT=10,FILE='\\.\pipe\testpipe',STATUS='OLD', ACTION='WRITE', useropen = uopen)
print*, "open called"
do i = 1, 10
write (10, *) 'Hello World!'
end do
close(10)
end subroutine
INTEGER FUNCTION UOPEN(FILENAME, DESIRED_ACCESS, SHARE_MODE, A_NULL, CREATE_DISP, FLAGS_ATTR, B_NULL, UNIT, FLEN)
!DEC$ ATTRIBUTES C, ALIAS:'_UOPEN' :: UOPEN
!DEC$ ATTRIBUTES REFERENCE :: FILENAME
!DEC$ ATTRIBUTES REFERENCE :: DESIRED_ACCESS
!DEC$ ATTRIBUTES REFERENCE :: SHARE_MODE
!DEC$ ATTRIBUTES REFERENCE :: CREATE_DISP
!DEC$ ATTRIBUTES REFERENCE :: FLAGS_ATTR
!DEC$ ATTRIBUTES REFERENCE :: UNIT
USE IFWIN
implicit none
integer*4 :: DESIRED_ACCESS, SHARE_MODE, CREATE_DISP, FLAGS_ATTR, UNIT, A_NULL, B_NULL, FLEN, hFile
CHARACTER*(FLEN) FILENAME
character*(FLEN+1) :: pipename
TYPE(T_SECURITY_ATTRIBUTES), POINTER :: NULL_SEC_ATTR
logical :: waitstatus
!FLAGS_ATTR = FLAGS_ATTR + FILE_FLAG_WRITE_THROUGH
DESIRED_ACCESS = GENERIC_WRITE
SHARE_MODE = 0
CREATE_DISP = OPEN_EXISTING
FLAGS_ATTR = FILE_ATTRIBUTE_NORMAL
pipename = '\\.\pipe\testpipe' // char(0)
waitstatus = WaitNamedPipe(pipename, 1000)
UOPEN = CreateFile( pipename, DESIRED_ACCESS, SHARE_MODE, NULL_SEC_ATTR, CREATE_DISP, 0, 0 )
RETURN
END function
end module
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Separate to your USEROPEN question - consider (if you wanted to customise the CreateFile or pipe connection in some way the following might not be applicable) just using a normal Fortran OPEN statement to open the pipe and handling the specific "pipe not available" error code (perhaps in a loop with some sort of delay between attempts. This is simpler and also avoids the race condition that exists in your current approach - there is a finite time between WaitNamedPipe and CreateFile where another process could steal the pipe.
I suspect what is happening is that you are relying on the debugger to find out what filename is, and the debugger is telling fibs - the actual filename is ok (and it already includes the null terminator). But do note that Fortran pointers and C pointers are different - you never define NULL_SEC_ATTR so the reference to it in the CreateFile call is an error. Instead simply pass NULL for that parameter.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
you're absolutely correct on both points. I had originally tried opening the pipe without the USEROPEN function, but failed because some of the parameters were wrong. now that I have all that worked out with the USEROPEN working, opening the pipe without USEROPEN is also working. Also, now that I have the remaining options correct, i was stopping in the debugger to inspect FILENAME, but never tried just passing FILENAME to CreateFile. THANKS!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here's the code i ended up with:
module fortranpipe
implicit none
contains
subroutine writetopipe()
!dec$ attributes dllexport :: writetopipe
!dec$ attributes alias : "writetopipe" :: writetopipe
use kernel32
implicit none
integer*4 :: i, ios, lasterror
logical :: waitstatus
character*17 :: pipename
pipename = '\\.\pipe\testpipe'
do
open(unit=10, file=pipename, status='OLD', action='WRITE', iostat=ios)
if (ios == 0) exit
waitstatus = WaitNamedPipe(pipename // char(0), 1000)
lasterror = GetLastError()
if (waitstatus == .false. .OR. lasterror /= 0) exit
end do
if (ios /= 0) then
! do something with the err
endif
print*, "open called"
do i = 1, 10
write (10, *) 'Hello World!'
end do
close(10)
end subroutine
end module

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