Fortran 和 C# 之间的管道

3
我想在Fortran程序和C#程序之间建立一个管道。Fortran程序将负责处理重要任务,而C#程序将提供一个“视图”,以查看从Fortran程序发送的数据。为了检查这是否可行,我编写了两个小程序。(Fortran代码是从在C++和C#之间传输数据的示例中获取的。)
Fortran代码:
  PROGRAM Test

  USE kernel32
  IMPLICIT NONE

  ! Data pipe
  INTEGER*4 EqnData /100/
  ! Paths for pipes
  CHARACTER*128 dataname /'\\.\pipe\EqnData'/

  INTEGER(HANDLE) :: pipe1

  pipe1 = CreateNamedPipe('\\\\.\\pipe\\EqnData'C, PIPE_ACCESS_DUPLEX, &
    PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, &
    1024, 1024, 120 * 1000, NULL)

  PRINT*, pipe1

  ! Open data pipe
  OPEN(UNIT=EqnData, FILE=dataname, ACCESS='STREAM', STATUS='OLD')

  READ* 

  ! Close pipe
  CLOSE(EqnData)

  WRITE (*,*) 'end'

  END

C# 代码:
using System;
using System.IO;
using System.IO.Pipes;

class PipeClient
{
  static void Main(string[] args)
  {

    using (NamedPipeClientStream pipeClient
      = new NamedPipeClientStream(".",
                             "EqnData",
                             PipeDirection.InOut))
    {
      // Connect to the pipe or wait until the pipe is available.
      Console.Write("Attempting to connect to pipe...");
      pipeClient.Connect();

      Console.WriteLine("Connected to pipe.");
      Console.WriteLine("There are currently {0} pipe server instances open.",
         pipeClient.NumberOfServerInstances);
      using (StreamReader sr = new StreamReader(pipeClient))
      {
        // Display the read text to the console
        string temp;
        while ((temp = sr.ReadLine()) != null)
        {
          Console.WriteLine("Received from server: {0}", temp);
        }
      }
    }
    Console.Write("Press Enter to continue...");
    Console.ReadLine();
  }
}

如果我启动这两个程序,我会看到Fortran代码创建了一个管道,并且进入了READ语句,但是C#代码只到达了pipeClient.Connect()然后就一直停在那里。

我是否正确设置了C#部分的内容?或者可能我在Fortran方面做得不太对,以至于C#客户端“看到”管道?

不确定以C结尾的字符串是否正确。在我使用的Fortran编译器上无法工作。尝试将CreateNamedPipe中反斜杠的数量减半。在读/写之前,您还需要ConnectNamedPipe。至少其中一个程序应该是写入的。如果两个程序都在读取,并且没有人在写入,则什么也不会发生。 - cup
以下链接可能会有所帮助:https://www.csharpcodi.com/vs2/241/AutoHotkey.Interop/src/AutoHotkey.Interop/Pipes/NamedPipeServer.cs/ - Tu deschizi eu inchid
你使用的是哪个Fortran编译器?我无法通过open/read/write让管道起作用。但它们可以与WriteFile和ReadFile一起工作,这些都是本地的Windows调用。 - cup
我正在使用英特尔Fortran。@cup的建议解决了问题。以下是可用的代码,供其他人参考。 - Alex M
1个回答

0

@Cup 是对的。添加一个管道连接并切换到WriteFile就可以了。 Fortran 代码:

  program Test

  use kernel32
  implicit none

  ! Pipes
  integer(HANDLE) :: pipe
  character*128 dataname /'\\.\pipe\EqnData'/
  ! Flags
  integer :: connectNamedPipeErrFlag, errorCode, writeFileErrFlag
  ! Data to send
  character*128 :: message

  pipe = CreateNamedPipe( &                       ! CreateNamesPipe: Creates an instance of a named pipe and returns a handle for subsequent pipe operations
    !                                               https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea
    '\\.\pipe\EqnData', &                         ! lpName: Unique pipe nam in th following form: \\.\pipe\pipename
    PIPE_ACCESS_DUPLEX, &                         ! dwOpenMode: Open mode (eg. PIPE_ACCESS_DUPLEX, PIPE_ACCESS_INBOUND, PIPE_ACCESS_OUTBOUND, etc.)
    PIPE_WAIT, &                                  ! dwPipeMode: Pipe mode (eg. PIPE_WAIT, etc.)
    PIPE_UNLIMITED_INSTANCES, &                   ! nMaxInstances: Maximum number of instances that can be created for this pipe
    1024, &                                       ! nOutBufferSize: Number of bytes to reserve for the output buffer
    1024, &                                       ! nInBufferSize: Number of bytes to reserve for the input buffer
    120 * 1000, &                                 ! nDefaultTimeOut: Default time-out value, in milliseconds
    NULL)                                         ! lpSecurityAttributes: A pointer to a SECURITY_ATTRIBUTES structure
  if(pipe .NE. INVALID_HANDLE_VALUE) then
    write (*,*) 'Pipe created'
  else
    ! TODO:
  endif

  connectNamedPipeErrFlag = ConnectNamedPipe( &   ! ConnectNamedPipe: Returned nonzero value if the connection is successful
    !                                               https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-connectnamedpipe
    pipe, &                                       ! hNamedPipe: Handle to the server end of a named pipe instance (returned by the CreateNamedPipe function)
    NULL)                                         ! lpOverlapped: A pointer to an OVERLAPPED structure
  if(connectNamedPipeErrFlag .NE. 0) then
    write(*,*) 'Pipe connected'
  else
    ! TODO:
  endif

  message = 'Some data'

  writeFileErrFlag = WriteFile( &                 ! Writes data to the specified file or IO device
    !                                               https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile
    pipe, &                                       ! hfile: A handle to the file or IO device
    loc(message), &                               ! lpBuffer: A pointer to the buffer containing the data to be written to the file or device.
    len(trim(message)), &                         ! nNumberOfBytesToWrite: Number of bytes to write
    0, &                                          ! lpNumberOfBytesWritten: number of bytes that were written
    NULL)                                         ! lpOverlapped:
  if (writeFileErrFlag .NE. 0) then
    write (*,*) 'Write successful'
  else
    errorCode = GetLastError()
    if(errorCode .EQ. ERROR_IO_PENDING) then
      ! TODO:
    elseif (errorCode .EQ. ERROR_INVALID_USER_BUFFER ) then
      ! TODO:
    elseif(errorCode .EQ. ERROR_NOT_ENOUGH_MEMORY ) then
      ! TODO:
    elseif(errorCode .EQ. ERROR_OPERATION_ABORTED) then
      ! TODO:
    elseif(errorCode .EQ. ERROR_NOT_ENOUGH_QUOTA) then
      ! TODO:
    else
      ! TODO:
    endif
  endif

  close(pipe)

  write(*,*) 'Pipe closed'

  end program

一个替代方案是 https://stackoverflow.com/questions/16619888/use-pipe-between-fortran-and-c - cup

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接