FILENAME is "undefined address" with USEROPEN

FILENAME is "undefined address" with USEROPEN

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

 

 

4 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

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.

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!

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

Leave a Comment

Please sign in to add a comment. Not a member? Join today