過去雑記

旧鯖時代の雑記です。新しいの。リンク切れに注意。


2007: 12345678910
2006: 123456789101112
2005: 123456789101112
2004: 456789101112

過去雑記

2007/8/2(木)

散財00:05:52

ドージンワーク#4, あねちっくセンセーション#2, ゆるめいつ#1。なんか4コマ買いすぎな気がします。

コメントはありません。

2007/8/15(水)

struct2byte[] for C#とほか22:01:10

C#でネットワーク通信を行いたい場合ソケットはbyte[]を要求します。しかし構造体をbyte[]に変換する方法は特に用意されていません。unsafeをつけない場合Marshalクラスを用いてやればできますが、2重にメモリを確保しメモリコピーが2回起きるのでどうにも気持ち悪く感じます。そこでunsafeコードを使用すると下記のようなコードになります。

unsafe static byte[] ToByteArray(Struct v) {
    byte[] ret = new byte[sizeof(Struct)];
    byte* p = (byte *)&v;
    for(int i = 0; i < ret.Length; i++)
        ret[i] = p[i];
    return ret;
}
unsafe static Hoge FromByteArray(byte[] v) {
    if(v.Length != sizeof(Struct))
        throw new ArithmeticException();
    Struct ret = new Hoge();
    byte* p = (byte *)&ret;
    for(int i = 0; i < v.Length; i++)
        p[i] = v[i];
    return ret;
}

これは問題なくコンパイルがとおり意図した結果を返します。しかしどうせならStructの部分を任意の構造体Tに対して行いたくなってくるわけです。そこでジェネリックを使用して次のようなコードを書いてみました。

unsafe static byte[] ToByteArray<T>(T v) where T:struct {
    byte[] ret = new byte[sizeof(T)];
    byte* p = (byte *)&v;
    for(int i = 0; i < ret.Length; i++)
        ret[i] = p[i];
    return ret;
}
unsafe static T FromByteArray<T>(byte[] v) where T:struct {
    if(v.Length != sizeof(Hoge))
        throw new ArithmeticException();
    T ret = default(T);
    byte* p = (byte *)&ret;
    for(int i = 0; i < v.Length; i++)
        p[i] = v[i];
    return ret;
}

しかしこれはコンパイルが通りません。コンパイルエラーを見るにTが参照型と認識されているようで無理なようです。型制約が意味をなしてない気がしますがどうなんでしょう?どうしても任意の型に対して行いたい場合C++/CLIを使って次のようにすればいけるみたいです。

generic<typename T> where T: value class
static array<System::Byte> ^ToByteArray(T value) {
    array<System::Byte> ^ret = gcnew array<System::Byte>(sizeof(T));
    pin_ptr<T> pin = &value;
    unsigned char* p = reinterpret_cast<unsigned char*>(pin);
    for(int i=0; i<ret->Length; i++)
        ret[i] = p[i];
    return ret;
}
generic<typename T> where T: value class
static T FromByteArray(array<System::Byte> ^value) {
    if(value->Length != sizeof(T))
        throw gcnew System::ArgumentException();
    T ret = gcnew T(); 
    pin_ptr<T> pin = &ret;
    unsigned char* p = reinterpret_cast<unsigned char*>(pin);
    for(int i=0; i<value->Length; i++)
        p[i] = value[i];
    return ret;
}

コメントはありません。

2007/8/17(金)

byte *b = (byte *)T; がコンパイルエラーになる理由00:06:54

駄目な理由がわかりました。C#では参照型をフィールドに含む構造体のポインタは取れないようです。だから不特定の構造体Tだとコンパイルエラーになるわけですね。

コメントはありません。

2007/8/29(水)

先月28日で6年目ということに気づいた23:41:17

6年目ですよ。去年はぐだぐだ路線とか言ってますが、今年はさらに輪をかけてぐだぐだ。目標は色々とありますが、目下動いてるのが2本あるのでそれを何とかしないとサイトまではむりかなぁ。

コメントはありません。

goto Top

Copyright(C)方位記号