Not a member of Pastebin yet?
                        Sign Up,
                        it unlocks many cool features!                    
                - using System;
 - using System.IO.Pipes;
 - using System.IO;
 - using System.Runtime.InteropServices;
 - using System.Threading;
 - namespace ConsoleApplication
 - {
 - class Program
 - {
 - /// <summary>
 - /// Performs some asyncronous action given a stream and returning a stream.
 - /// </summary>
 - /// <param name="inputStream">Represents the native HANDLE of an AnonymousPipeServerStream.</param>
 - /// <param name="outputStream">A native pointer which can be used with an AnonymousPipeClientStream.</param>
 - [DllImport("foo.dll")]
 - private extern static void Bar(IntPtr source, IntPtr destination);
 - static void Main(string[] args)
 - {
 - // This is a sample showing how you might use the class:
 - string sourceFile = @"c:\list.txt";
 - string destinationFile = @"c:\list_out.txt";
 - using (Stream source = File.OpenRead(sourceFile))
 - {
 - using (Stream destination = File.Open(destinationFile, FileMode.OpenOrCreate))
 - {
 - NativeStreamInOutWrapper.Execute(new NativeStreamInOutWrapper.NativeStreamInOutMethod(Bar), source, destination);
 - }
 - }
 - }
 - /* SAMPLE NATIVE C CODE:
 - #include <stdio.h>
 - #include <stdbool.h>
 - #include <string.h>
 - #include <unistd.h>
 - #include <Windows.h>
 - #include <io.h>
 - #include <fcntl.h>
 - #define DLLEXPORT __declspec(dllexport) __cdecl
 - extern void DLLEXPORT Bar(HANDLE source, HANDLE destination)
 - {
 - // Open the source stream (for reading):
 - int sourceFD = _open_osfhandle((intptr_t)source, _O_RDONLY);
 - FILE * sourceStream = _fdopen(sourceFD, "r");
 - // Open the destination stream (for writing):
 - int destinationFD = _open_osfhandle((intptr_t)destination, _O_APPEND);
 - FILE * destinationStream = _fdopen(destinationFD, "w");
 - // SAMPLE CODE:
 - // Here you would call your real method which takes (FILE *, FILE *)
 - int val = 0;
 - while (0 < (val = getc(sourceStream)))
 - {
 - // Write the input into the output
 - // followed by the "-" character:
 - putc(val, destinationStream);
 - putc('-', destinationStream);
 - // Continuously flush:
 - fflush(destinationStream);
 - }
 - // Write the null terminator to the output stream:
 - putc(0, destinationStream);
 - // Flush any buffered data into the output stream:
 - fflush(destinationStream);
 - // Close the source and destination streams:
 - fclose(sourceStream);
 - fclose(destinationStream);
 - }
 - */
 - /// <summary>
 - /// This class allows you to work with native methods
 - /// which need to use FILE * s to read input and write
 - /// output to. From within the native methods you could,
 - /// for example, use this to get the native application
 - /// to take STDIN from a stream and STDOUT to a stream.
 - /// </summary>
 - public static class NativeStreamInOutWrapper
 - {
 - public delegate void NativeStreamInOutMethod(IntPtr source, IntPtr destination);
 - /// <summary>
 - /// Executes a native method which takes two HANDLE parameters
 - /// to anonymous pipes and streams the data from the source stream
 - /// into the source pipe and from the destination pipe to the destination
 - /// stream.
 - /// </summary>
 - /// <param name="method">The method to call.</param>
 - /// <param name="source">The source data stream.</param>
 - /// <param name="destination">The destination data stream.</param>
 - public static void Execute(NativeStreamInOutMethod method, Stream source, Stream destination)
 - {
 - Execute(method, source, destination, 1, 30000, true);
 - }
 - /// <summary>
 - /// Executes a native method which takes two HANDLE parameters
 - /// to anonymous pipes and streams the data from the source stream
 - /// into the source pipe and from the destination pipe to the destination
 - /// stream.
 - /// </summary>
 - /// <param name="method">The method to call.</param>
 - /// <param name="source">The source data stream.</param>
 - /// <param name="destination">The destination data stream.</param>
 - /// <param name="bufferSize">The buffer size to use.</param>
 - /// <param name="timeout">The timeout in milliseconds before the operation is aborted.</param>
 - /// <param name="continuousFlush">Whether the stream is flushed after every write of the buffer.</param>
 - public static void Execute(NativeStreamInOutMethod method, Stream source, Stream destination,
 - int bufferSize, int timeout, bool constantFlush)
 - {
 - // source --> sourcePipe |Native| destinationPipe --> destination
 - // Construct the anonymous pipes we'll need to stream data to/from
 - // the native method:
 - using (AnonymousPipeServerStream sourcePipe = new AnonymousPipeServerStream(
 - PipeDirection.Out, HandleInheritability.Inheritable))
 - {
 - using (AnonymousPipeServerStream destinationPipe = new AnonymousPipeServerStream(
 - PipeDirection.In, HandleInheritability.Inheritable))
 - {
 - // This mutex waits for the native process to complete:
 - // << NOTE: The native process should block until it recieves
 - // the null terminator on the source stream. >>
 - ManualResetEvent processComplete = new ManualResetEvent(false);
 - // This mutex waits for us to finish pumping the destination stream:
 - ManualResetEvent dumpComplete = new ManualResetEvent(false);
 - // This thread will pump the source stream into the sourcePipe:
 - Thread sourcePump = new Thread(new ParameterizedThreadStart(PumpSourceBuffer));
 - sourcePump.Start(new PumpSourceStartArguments()
 - {
 - source = source,
 - sourcePipe = sourcePipe,
 - bufferSize = bufferSize,
 - mutex = processComplete,
 - constantFlush = constantFlush
 - });
 - // This thread will pump the destinationPipe into the destination:
 - Thread destinationPump = new Thread(new ParameterizedThreadStart(PumpDestinationBuffer));
 - destinationPump.Start(new PumpDestinationStartArguments()
 - {
 - destination = destination,
 - destinationPipe = destinationPipe,
 - bufferSize = bufferSize,
 - mutex = dumpComplete,
 - constantFlush = constantFlush
 - });
 - // This is the native method which will process data from
 - // the sourcePipe and dump data into the destinationPipe:
 - Thread t = new Thread(new ParameterizedThreadStart(Process));
 - t.Start(new ProcessStartArguments()
 - {
 - sourcePipe = sourcePipe,
 - destinationPipe = destinationPipe,
 - nativeMethod = method,
 - mutex = processComplete
 - });
 - processComplete.WaitOne();
 - dumpComplete.WaitOne();
 - }
 - }
 - }
 - #region Native Method Call
 - private class ProcessStartArguments
 - {
 - public AnonymousPipeServerStream sourcePipe;
 - public AnonymousPipeServerStream destinationPipe;
 - public ManualResetEvent mutex;
 - public NativeStreamInOutMethod nativeMethod;
 - }
 - private static void Process(Object o)
 - {
 - ProcessStartArguments args = (ProcessStartArguments)o;
 - // Call out to the operation, passing the outPipe handle,
 - // and getting back the handle we'll use for the inPipe:
 - args.nativeMethod(args.sourcePipe.ClientSafePipeHandle.DangerousGetHandle(),
 - args.destinationPipe.ClientSafePipeHandle.DangerousGetHandle());
 - args.sourcePipe.DisposeLocalCopyOfClientHandle();
 - args.destinationPipe.DisposeLocalCopyOfClientHandle();
 - // Let everyone know we've finished with the native
 - // method call:
 - args.mutex.Set();
 - }
 - #endregion
 - #region Destination Pump
 - private class PumpDestinationStartArguments
 - {
 - public Stream destination;
 - public AnonymousPipeServerStream destinationPipe;
 - public ManualResetEvent mutex;
 - public int bufferSize;
 - public bool constantFlush;
 - }
 - private static void PumpDestinationBuffer(Object o)
 - {
 - PumpDestinationStartArguments args = (PumpDestinationStartArguments)o;
 - byte[] buffer = new byte[args.bufferSize];
 - int len = 0;
 - while (0 != (len = args.destinationPipe.Read(buffer, 0, args.bufferSize)))
 - {
 - args.destination.Write(buffer, 0, len);
 - if (args.constantFlush) args.destination.Flush();
 - // Wait for the null terminator:
 - if (buffer[len - 1] == 0) break;
 - }
 - // Flush any buffered data into the pipe:
 - args.destination.Flush();
 - // Let everyone know we've finished processing the
 - // data from the stream:
 - args.mutex.Set();
 - }
 - #endregion
 - #region Source Pump
 - private class PumpSourceStartArguments
 - {
 - public Stream source;
 - public AnonymousPipeServerStream sourcePipe;
 - public ManualResetEvent mutex;
 - public int bufferSize;
 - public bool constantFlush;
 - }
 - private static void PumpSourceBuffer(Object o)
 - {
 - PumpSourceStartArguments args = (PumpSourceStartArguments)o;
 - int len = 0;
 - byte[] buffer = new byte[args.bufferSize];
 - while (0 != (len = args.source.Read(buffer, 0, args.bufferSize)))
 - {
 - args.sourcePipe.Write(buffer, 0, len);
 - if (args.constantFlush) args.sourcePipe.Flush();
 - }
 - // Write the null terminator:
 - args.sourcePipe.WriteByte(0);
 - // Flush any buffered data into the pipe:
 - args.sourcePipe.Flush();
 - // Wait for the reciever to take all of our data.
 - args.sourcePipe.WaitForPipeDrain();
 - // Wait for the native process to complete:
 - args.mutex.WaitOne();
 - }
 - #endregion
 - }
 - }
 - }
 
Advertisement
 
                    Add Comment                
                
                        Please, Sign In to add comment