byte[] -> T*への道
ここのところずっとやっていたネタですが、実はこんな事しなくても良いことが判明して使い道が無くなってしまいました。(^^; ま、折角なので日記ネタとして継続します。
T*がコンパイル出来ないのはC#の制限なので、ILアセンブラで書いてしまうことに。
C#では書けないコード
public static unsafe T* Foo<T>(byte[] bytes) { return (T*) Marshal.UnsafeAddrOfPinnedArrayElement(bytes, 0); }
コイツをILで書くと
.method public hidebysig static !!T* Foo<T>(uint8[] bytes) cil managed { // コード サイズ 18 (0x12) .maxstack 2 .locals init (!!T* V_0) IL_0000: nop IL_0001: ldarg.0 IL_0002: ldc.i4.0 IL_0003: call native int [mscorlib]System.Runtime.InteropServices. Marshal::UnsafeAddrOfPinnedArrayElement(class [mscorlib]System.Array, int32) IL_0008: call void* [mscorlib]System.IntPtr::op_Explicit(native int) IL_000d: stloc.0 IL_000e: br.s IL_0010 IL_0010: ldloc.0 IL_0011: ret } // end of method App::Foo
こんな感じ。!!T*に注目です。
ちなみに呼び出しは、
IL_0015: call !!0* App::Foo(uint8[])
generic型が!!Tではなく!!0になっているのに注意です。多分、0番目の型パラメータという意味だと思います。
結局、ILで書いてもメソッドのパラメータにT*があるとC#でコンパイル出来ないし、Tに戻すと値型なのでコピーが発生してしまい、使えないということでボツとなりました。(^^;