WZero3 でアプリを書いていて、接続の制御をしようとして適当に書いていたら、動かない。ちょっと調べてみたら、.NET Compact Framework は .NET Framework のサブセットなので完全な .NET Framework の方法とはやや異なる。ということで、注意が必要。
Microsoft .NET Compact Framework の P/Invoke とマーシャリング入門Microsoft .NET Compact Framework での高度な P/Invoke ぐちゃぐちゃ書いてあって、わかりにくいので、簡単にポイントだけ整理する。
.NET Compact Framework の相違点の概要
構造体内の文字列のマーシャリング
構造体内の固定長文字列のマーシャリング
—————— class Memory のC#版
using System;
using System.Runtime.InteropServices; using System.ComponentModel; namespace Uchukamen.WZero3
{ class Memory { [DllImport("coredll.dll", SetLastError = true)] private static extern IntPtr LocalAlloc(int uFlags, int uByte); [DllImport("coredll.dll", SetLastError = true)]
private static extern IntPtr LocalFree(IntPtr hMem); [DllImport("coredll.dll", SetLastError = true)]
private static extern IntPtr LocalReAlloc(IntPtr hMem, int uBytes, int fuFlags); private const int LMEM_FIXED = 0;
private const int LMEM_MOVEABLE = 2; private const int LMEM_ZEROINIT = 0x40; private const int LPTR = LMEM_FIXED | LMEM_ZEROINIT;
// LocalAlloc を使用して、メモリ ブロックを割り当てます。
public static IntPtr AllocHLocal(int cb) { return LocalAlloc(LPTR, cb); } // AllocHLocal で割り当てられたメモリを解放します。
public static void FreeHLocal(IntPtr hlocal) { if (!hlocal.Equals(IntPtr.Zero)) { if (!IntPtr.Zero.Equals(LocalFree(hlocal))) { throw new Win32Exception(Marshal.GetLastWin32Error()); } hlocal = IntPtr.Zero; } } // 以前に AllocHLocal で割り当てられたメモリ ブロックのサイズを変更します。
public static IntPtr ReAllocHLocal(IntPtr pv, int cb) { IntPtr newMem = LocalReAlloc(pv, cb, LMEM_MOVEABLE); if (newMem.Equals(IntPtr.Zero)) { throw new OutOfMemoryException(); } return newMem;
} // マネージ文字列の内容をアンマネージ メモリにコピーします。
public static IntPtr StringToHLocalUni(string s) { if (s == null) return IntPtr.Zero; else { int nc = s.Length; int len = 2 * (1 + nc); IntPtr hLocal = AllocHLocal(len); if (hLocal.Equals(IntPtr.Zero)) throw new OutOfMemoryException(); else { Marshal.Copy(s.ToCharArray(), 0, hLocal, s.Length); return hLocal; } } } } } |