Fortran 和 C# 之间的管道
Pipe between Fortran and C#
我想在 Fortran 程序和 C# 程序之间建立一个管道。 Fortran 程序将完成繁重的工作,而 C# 程序将提供一个 'view' 来说明正在做什么(使用从 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# 客户端 'sees' 管道?
@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://docs.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://docs.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://docs.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
我想在 Fortran 程序和 C# 程序之间建立一个管道。 Fortran 程序将完成繁重的工作,而 C# 程序将提供一个 'view' 来说明正在做什么(使用从 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# 客户端 'sees' 管道?
@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://docs.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://docs.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://docs.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