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より後にあるフィールドのアドレスがすべてずれていくので、ひどいことになります。この解決策をいくつか考えてみます。

続きを読む

IntPtrが示すバイト列のポインタをGZipStream/DeflateStreamで圧縮・展開する

.NET Frameworkでは、System.IO.Compression.GZipStreamSystem.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);
    }
}

このように、ReadWriteメソッドを使ってデータを読み書きするのですが、これらのメソッドは引数にbyte[]をとります。ですから、アンマネージなバイト列の先頭ポインタ(IntPtr)を持っていた場合はそのままでは圧縮できません。これを何とかしてがんばる方法をいくつか考えてみました。

なお、展開の方も同様の考え方で行えるため、ここでは割愛します。

続きを読む

OpenCvSharpをつかう その10 (Star Detector)

このところOpenCvSharpの使い方というよりはただのOpenCV 2.0の新機能紹介になっているこのシリーズですが、今回はStar Detector(日本語だとStar検出器?)のサンプルを作ってみたのでご紹介します。Star Detectorの関数はOpenCV 2.0で追加されました。

続きを読む