size_tのマーシャリング
以下のようなCの構造体について、P/InvokeのためにC#で同等の構造体を定義するとします。
typedef struct Hoge { size_t size; int x; }Hoge;
32bit環境に限れば、size_t は普通 unsigned int ですから、C#では以下のようになります。
[StructLayout(LayoutKind.Sequential)] struct Hoge { public uint size; public int x; }
しかし、もし64bit環境なら、size_t は64bit値です。だいたい以下のような定義になっています。
typedef unsigned __int64 size_t; // Visual C++ typedef unsigned long size_t; // gcc
すなわちC#でいうところの ulong です。
よって、上記のC#のHoge構造体は64bit環境では問題となります。64bitではsizeより後にあるフィールドのアドレスがすべてずれていくので、ひどいことになります。この解決策をいくつか考えてみます。
続きを読むtwitterを公開にしました
かれこれ2年半以上protectedだったので勇気がいりますね。
http://twitter.com/Schima
IntPtrが示すバイト列のポインタをGZipStream/DeflateStreamで圧縮・展開する
.NET Frameworkでは、System.IO.Compression.GZipStreamやSystem.IO.Compression.DeflateStreamクラスを用いて、データを圧縮・展開することができます。この2つのクラスは全く同じように使えるため、以下ではGZipStreamで話を進めます。
以下のコードは、指定したbyte配列をGZipStreamで圧縮してMemoryStreamに出力するサンプルです。MemoryStreamのところをFileStreamにすればメモリではなくファイルに書き出すこともできます。
using System.IO; using System.IO.Compression; using System.Text; class Program { static void Compress(MemoryStream ms, byte[] data) { using (GZipStream gzs = new GZipStream(ms, CompressionMode.Compress)) { gzs.Write(data, 0, data.Length); } } static void Main(string[] args) { MemoryStream ms = new MemoryStream(); byte[] data = Encoding.UTF8.GetBytes("hogehogefugafugapiyopiyo"); Compress(ms, data); } }
このように、ReadやWriteメソッドを使ってデータを読み書きするのですが、これらのメソッドは引数にbyte[]をとります。ですから、アンマネージなバイト列の先頭ポインタ(IntPtr)を持っていた場合はそのままでは圧縮できません。これを何とかしてがんばる方法をいくつか考えてみました。
なお、展開の方も同様の考え方で行えるため、ここでは割愛します。
続きを読む