.NET Framework
プラットフォーム呼び出し
サーチ…
構文
- [DllImport( "Example.dll")]静的なextern void SetText(string inString);
- [DllImport( "Example.dll")]静的extern void GetText(StringBuilder outString);
- [MarshalAs(UnmanagedType.ByValTStr、SizeConst = 32)]文字列テキスト。
- [MarshalAs(UnmanagedType.ByValArray、SizeConst = 128)] byte [] byteArr;
- [StructLayout(LayoutKind.Sequential)] public struct PERSON {...}
- [StructLayout(LayoutKind.Explicit)] public構造体MarshaledUnion {[FieldOffset(0)] ...}
Win32のdll関数を呼び出す
using System.Runtime.InteropServices;
class PInvokeExample
{
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern uint MessageBox(IntPtr hWnd, String text, String caption, int options);
public static void test()
{
MessageBox(IntPtr.Zero, "Hello!", "Message", 0);
}
}
static extern
stll DllImportAttribute
として、 Value
プロパティを.dll nameに設定して関数を宣言します。 System.Runtime.InteropServices
名前空間を使用することを忘れないでください。その後、通常の静的メソッドとして呼び出します。
Platform Invocation Servicesは、.dllの読み込みと目的の検索を行います。ほとんどの単純なケースでは、P / Invokeはパラメータをマーシャリングして.dllとの間で戻り値を返します(つまり、.NETデータ型からWin32データ型への変換、逆もまた同様です)。
Windows APIの使用
pinvoke.netを使用してください。
あなたのコードでextern
Windows API関数を宣言する前に、 pinvoke.netでそれを探すことを検討してください。彼らはすでに、すべてのサポートタイプと良い例で適切な宣言を持っている可能性が最も高いでしょう。
配列のマーシャリング
単純型の配列
[DllImport("Example.dll")]
static extern void SetArray(
[MarshalAs(UnmanagedType.LPArray, SizeConst = 128)]
byte[] data);
文字列の配列
[DllImport("Example.dll")]
static extern void SetStrArray(string[] textLines);
構造体をマーシャリングする
シンプルな構造体
C ++シグネチャ:
typedef struct _PERSON
{
int age;
char name[32];
} PERSON, *LP_PERSON;
void GetSpouse(PERSON person, LP_PERSON spouse);
C#の定義
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct PERSON
{
public int age;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string name;
}
[DllImport("family.dll", CharSet = CharSet.Auto)]
public static extern bool GetSpouse(PERSON person, ref PERSON spouse);
配列フィールドが不明な構造体。合格
C ++署名
typedef struct
{
int length;
int *data;
} VECTOR;
void SetVector(VECTOR &vector);
管理コードから非管理コードに渡すと、これは
data
配列はIntPtrとして定義する必要があり、メモリはMarshal.AllocHGlobal()
明示的に割り当てられなければなりません( Marshal.FreeHGlobal()
後に解放されます)。
[StructLayout(LayoutKind.Sequential)]
public struct VECTOR : IDisposable
{
int length;
IntPtr dataBuf;
public int[] data
{
set
{
FreeDataBuf();
if (value != null && value.Length > 0)
{
dataBuf = Marshal.AllocHGlobal(value.Length * Marshal.SizeOf(value[0]));
Marshal.Copy(value, 0, dataBuf, value.Length);
length = value.Length;
}
}
}
void FreeDataBuf()
{
if (dataBuf != IntPtr.Zero)
{
Marshal.FreeHGlobal(dataBuf);
dataBuf = IntPtr.Zero;
}
}
public void Dispose()
{
FreeDataBuf();
}
}
[DllImport("vectors.dll")]
public static extern void SetVector([In]ref VECTOR vector);
配列フィールドが不明な構造体。受信
C ++シグネチャ:
typedef struct
{
char *name;
} USER;
bool GetCurrentUser(USER *user);
そのようなデータがアンマネージコードから渡され、アンマネージ関数によってメモリが割り当てられると、マネージドコール側はそれをIntPrt
変数に受け取り、そのバッファをマネージド配列に変換するIntPrt
ます。文字列の場合、便利なMarshal.PtrToStringAnsi()
メソッドがあります:
[StructLayout(LayoutKind.Sequential)]
public struct USER
{
IntPtr nameBuffer;
public string name { get { return Marshal.PtrToStringAnsi(nameBuffer); } }
}
[DllImport("users.dll")]
public static extern bool GetCurrentUser(out USER user);
組合のマーシャリング
値型フィールドのみ
C ++宣言
typedef union
{
char c;
int i;
} CharOrInt;
C#宣言
[StructLayout(LayoutKind.Explicit)]
public struct CharOrInt
{
[FieldOffset(0)]
public byte c;
[FieldOffset(0)]
public int i;
}
値型フィールドと参照フィールドを混在させる
値タイプ1の参照値を重複させることはできません。 のためにコンパイルされませんFieldOffset(0) text; FieldOffset(0) i;
typedef union
{
char text[128];
int i;
} TextOrInt;
一般的にカスタムマーシャリングを使用する必要があります。しかし、特にこのようなより単純なテクニクスの場合は、次のように使用できます。
[StructLayout(LayoutKind.Sequential)]
public struct TextOrInt
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
public byte[] text;
public int i { get { return BitConverter.ToInt32(text, 0); } }
}