C#とC++の相互運用のための属性の設定方法

C#からC++のコードにアクセスするためには、カスタム属性を使用して関数や構造体の挙動を調整する必要があります。

DllImport属性

DLLエントリポイントを定義する外部関数を示すことで、DLLの関数を呼び出せるようになります。

[ DllImport( "DLL名" ) ]
DllImportAttribute クラス (System.Runtime.InteropServices) | MSDN
属性のパラメータ
パラメータ 説明 既定値
EntryPoint DLL内の関数の名前  
CharSet 文字列のマーシャリング方法を示すCharSet列挙 CharSet.Auto
SetLastError Win32エラー情報を維持するか? false
ExactSpelling EntryPointの関数名を厳密に一致させるか? false
PreserveSig 定義通りのメソッドのシグネチャを維持するか?  
CallingConvention EntryPointで使用するモードを指定するCallingConvention列挙 StdCall

実行時に指定のDLLを読み込めないと、モジュールが見つからないとしてFileNotFoundExceptionやDllNotFoundExceptionが発生します。

呼び出し規約 (calling convention)

CallingConvention列挙型で、アンマネージド コードを呼び出すための呼び出し規約の指定をします。

CallingConvention 列挙型
メンバ 説明
Cdecl 呼び出しが、スタックを消去。これはPrintfなどの可変引数のメソッドの呼び出しで使用する
StdCall 呼び出しが、スタックを消去。アンマネージ関数を呼び出す既定値
ThisCall 最初の引数がthisポインタ。アンマネージドDLLからエクスポートしたクラスのメソッドを呼び出すために使用する
Winapi プラットフォームに応じた、既定の呼び出し規約を使用する
(WindowsではStdCall、Windows CE.NETではCdecl)
FastCall サポートされない
CallingConvention 列挙型 (System.Runtime.InteropServices) | MSDN

サンプルコード

[DllImport( "test.dll", EntryPoint = "MethodName" )]
public static void MethodName( int x );

StructLayout属性

クラスまたは構造体のデータメンバを、メモリ内でどのように配置するかを表わせます。

[ StructLayout( LayoutKind列挙 ) ]
StructLayoutAttribute クラス (System.Runtime.InteropServices) | MSDN
LayoutKind列挙型
メンバ 説明
Sequential 宣言される順番に従って並べる
Explicit FieldOffsetAttributeで独自のオフセットを指定して並べる
Auto 適切なレイアウトで並べる
(マネージコードの外からアクセスできない)
属性のパラメータ
パラメータ 説明 既定値
Pack

パックサイズを指定するint値

指定可能な値は[ 1, 2, 4, 8, 16]のいずれか

8
CharSet 文字列のマーシャリング方法を示すCharSet列挙 CharSet.Auto
Size 構造体またはクラスのサイズを指定  

サンプルコード

[StructLayout( LayoutKind.Sequential )]
public struct Position
{
    public double x;
    public double y;
    public double z;
}

CLSCompliant属性

CLSへの準拠を検証するかどうかをコンパイラに指示します。

外部から参照できない型やメンバに、この属性を指定する必要はありません。指定すると「このアセンブリの外から認識できないため、CLS準拠の確認は '型' で実行されません」と警告が表示されます。

サンプルコード

[CLSCompliant( false )]
public int SetValue( UInt32 value );
※この場合UInt32型はCLSに準拠しないため、CLSCompliant(false)と指定する必要があります。

SuppressUnmanagedCodeSecurity属性

アンマネージコードの呼び出し時に実行されたスタックウォークを実行時に省き、効率を大幅に向上させます。SuppressUnmanagedCodeSecurityAttribute クラス | MSDN

MarshalAs属性

マネージ コードとアンマネージ コードで、データをマーシャリングする方法を指定します。MarshalAsAttribute クラス (System.Runtime.InteropServices) | MSDN

In属性 / Out属性

データの渡し方を指示します。

属性 説明
In属性 呼び出し側にデータをマーシャリングして渡すことを示す
Out属性 呼び出し元にデータをマーシャリングして戻すことを示す
void Foo([in] int[] array);

参考

MSDN (Microsoft Developer Network) から検索