How can I stream data (text) from a managed assembly to a native library and stream data (text) back to the managed assembly?
Specifically, I want to expose a System.IO.Stream
of some sort on the .NET side, and (most importantly) a FILE *
on the native side.
The signature of the native method should be:
FILE * foo(FILE * bar);
The signature of a wrapper around the native p/invoke call should be:
CustomStream foo(CustomStream bar);
I do not want to use callback methods on the native side (one for getting more data and one for setting more data). I want to use a FILE *
on the native side - and all of the associated methods which operate upon it such as fprintf
.
I do not want any disk I/O. This needs to be an in-memory operation.
I have complete control over both the managed assembly and the native library.
The solution must work with .NET 2.0
I'm willing to create any sort of managed or unmanaged shim layer required to pull this off.
The "obvious" solution is to use STDIN
and STDOUT
and launch a child process - however I don't want a separate process. Also, my attempts to redirect the STDIN
and STDOUT
streams of a native library which isn't a console application on Windows have failed somewhat spectacularly (and with much head-banging).
Based on this question:
Redirect stdout+stderr on a C# Windows service I attempted to modify the approach to (at least) solve the "response" stream half of my problem - but without a FileStream
(since I want something more analogous to a MemoryStream
). However, FileStream
is the only stream type which exposes a suitable low-level stream handle.
Otherwise, I'm pretty well stuck and am currently thinking I'll need to dive deeper and come up with my own hand-rolled native<->managed stream implementation but don't really know where to start.
Finally!
I've posted a complete sample project here:
http://pastebin.com/jcjHdnwz
This is for .NET 3.5 and uses the AnonymousPipeServerStream
- but with a little bit of reflector-ing, it's easy enough to duplicate the inner workings of the AnonymousPipeServerStream
in .NET 2.0.
Thanks for your help shf301 for pointing me to the native pipe API, which got me looking into the Microsoft docs for a better understanding of what's going on, and for pointing out I needed to use the _open_osfhandle
method to get the FILE *
reference.
You should be able to do this using a AnonymousPipeStream in .NET 3.5 or higher. That exposes a handle, via the SafePipeHandle
property that you can pass to SetStdHandle
.
For .NET 2.0 you may have to P/Invoke to the unmanaged pipe API.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With