管理されたアセンブリからネイティブライブラリにデータをストリーミングして元に戻すにはどうすればよいですか?

管理アセンブリからデータ(テキスト)をネイティブライブラリにストリームし、データ(テキスト)を管理アセンブリにストリームするにはどうすればよいですか?

具体的には、.NET側で何らかの並べ替えの System.IO.Stream を公開し、 FILE * を(最も重要なネイティブ側で

ネイティブメソッドのシグネチャは次のとおりです。

FILE * foo(FILE * bar);

ネイティブp/invoke呼び出しのラッパーのシグネチャは、次のようになります。

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/Oをしたくありません。これはメモリ内操作である必要があります。

マネージドアセンブリとネイティブライブラリの両方を完全に制御できます。

ソリューションは.NET 2.0で動作する必要があります

私はこれを取り除くために必要な管理されたまたは管理されていないシム層の任意の種類を作成するつもりです。

"明白な"解決策は、 STDIN STDOUT を使用して子プロセスを起動することです。また、Windows上でコンソールアプリケーションではないネイティブライブラリの STDIN ストリームと STDOUT ストリームをリダイレクトしようとすると、やや驚異的な失敗に終わりました。 。

この質問に基づいて: C#Windowsサービスでstdout + stderrをリダイレクトする私の問題の半分の "応答"ストリームを解決する(少なくとも)が、 FileStream MemoryStream と似たものが必要なので)しかし、 FileStream は、適切な低レベルのストリームハンドルを公開する唯一のストリームタイプです。

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.


溶液

最後に!

私はここに完全なサンプルプロジェクトを投稿しました:

http://pastebin.com/jcjHdnwz

これは.NET 3.5用であり、 AnonymousPipeServerStream を使用していますが、少し反射しても.NET 2.0では AnonymousPipeServerStream の内部動作を複製するのは簡単です。

何が起こっているのかをより良く理解するためにMicrosoftのドキュメントを調べてくれたネイティブパイプAPIを私に指摘してくれたあなたの助けてくれたshf301 のおかげで、 _open_osfhandle メソッドを使用して、 FILE * 参照を取得します。

10
@yahia、いいえ、サイズはすべてのコンテンツが読み取られるまで不明です。はい、読み込まれて処理されたデータは破棄されます...しかし、私は細部が手元の問題と直行していると思います。データチャンクはネットワーク上でストリーミングすることができるので、私はそれらをつかみ、できるだけ早くそれらを押し出す必要があります。
追加された 著者 Steve,
@ Yahia、あなたは「交換されたデータチャンクは既知の最大サイズを持っているのですか」と尋ねました。私の答えは「いいえ、実際にはありません」というものです。「データチャンクはネットワーク上でストリーミングできるので、可能。"これは、両方向のFIFOストリームを持つネイティブ関数と相互作用したいのです... .NETの側では、 Stream を取得して Streamに書き込むようになります。また、クロスプラットフォームのライブラリであるため、FILE *は他のプラットフォームでもうまく機能しています。
追加された 著者 Steve,
@ shf301、私はあなたが _open_osfhandle メソッドで何かをしていると思いますが、私は ClientSafePipeHandle.DangerousGetHandle()の値を使ってそれを行い、-1を返します。 SafePipeHandle.DangerousGetHandle()を使用すると(最終的に FILE * を返すという意味で)、パイプの端が間違っていて何も動作しません。
追加された 著者 Steve,
@Yahia、はい。一日の終わりには、それは非常に特異な要件です。
追加された 著者 Steve,
@JeffMercado、Win32関数 SetStdHandle AFAIKは適切なパイプへのハンドルを必要とし、 MemoryStream はこれを提供しません。 .SafeFileHandle.DangerousGetHandle()
追加された 著者 Steve,
@スティーブOK ...知られているストリームの最大のsizですか?または、交換されたデータチャンクは既知の最大サイズを持っていますか?
追加された 著者 Yahia,
@Steveネットワークが何をしなければならないのか分かりません。同じプロセス内で.NETとネイティブの間の通信についてこれを書いていますが...明確にすることはできますか?
追加された 著者 Yahia,
ネイティブ側の FILE * は絶対必要ですか?
追加された 著者 Yahia,
@Steveは理解しています... Windowsの場合は、他のほとんどの性能を上回るアーキテクチャを提案しています...しかし、FILE *と未知のサイズとクロスプラットフォームのチャンクは私の考えが当てはまりませんので...あなたが探しているものを見つけることに成功してほしい...
追加された 著者 Yahia,
はい、書き込み可能なハンドルを取得するにはパイプが必要です。 .NET 3.5
追加された 著者 Hans Passant,
@Steve - HANDLE から FILE * に移動する方法については、以下の質問への回答を参照してください。 stackoverflow .com/questions/7369445 /&hellip;
追加された 著者 shf301,
FileStream MemoryStream に置き換えてください。ここで重要なことは、ストリームが StreamWriter にラップされ、ライターが新しい標準出力ストリームとエラーストリームとして渡されることです。
追加された 著者 Jeff Mercado,
@スティーブ:ああ、私は違いを知らなかったし、自分自身を試していない。
追加された 著者 Jeff Mercado,

1 答え

これを行うには、 AnonymousPipeStream .NET 3.5以上。これは、 SetStdHandle に渡すことができる SafePipeHandle プロパティを介してハンドルを公開します。

.NET 2.0では、アンマネージパイプAPIにP/Invokeする必要があります。

11
追加された
あなたは私を解決策に導いてくれました。今私はそれを働かせています...私にそれをパッケージ化して投稿するビットを与えてください。私はあなたに信用を与えるでしょう。
追加された 著者 Steve,
私の編集を見てください。これは私がこれを試したことと失敗したところを示しています。
追加された 著者 Steve,
私は250ポイントの賞金を加えました。 「管理されていないパイプAPI」への参照を拡張できますか?
追加された 著者 Steve,
@Steve - P/Invokeを使用してパイプを作成するために管理されていない CreatePipe 関数を呼び出し、パイプから読み込む ReadFile を使用することです。 Msdnとpinvoke.netを参照してください。 msdn.microsoft.com/ en-us/library/windows/desktop /&hellip; - ピンボケ。 net/default.aspx/kernel32.createpipe
追加された 著者 shf301,
@ Steveには、C#用の名前付きパイプラッパークラスもあります。それはおそらくそのまま動作するはずです。 codeguru.com/Csharp/.NET/net_general/performance /article.php‌ /&hellip;
追加された 著者 shf301,