C# Programming

Image

相互運用 (Interop)

開発環境: Visual Studio 2003 

1.目次

2.目的

Unmagaged Code との相互運用について、本当はこんなことしたくないんだけど、どうしても使わざるを得ないときがあるので、メモっておきます。

3.参考書

(1) GotDotNet
(2) MSDN

4.マネージ コードから Win32 API のようなアンマネージ DLL 関数の呼び出し方法

たとえば、User32.dll の MessageBox 関数を指定する場合、
[DllImport("user32.dll", EntryPoint="MessageBox")]
public static extern int MsgBox(int hWnd, String text, String caption, uint type);
このときの DllImport のパラメータは次のとおり。

フィールド デフォルト値 説明
EntryPoint-呼び出される DLL エントリ ポイント。
定義内の関数の名前が DLL 内のエントリ ポイントと同じである場合は、明示的に指定する必要はありません。
CharSet CharSet.Ansi一部の API は、文字列引数がナロー (ANSI) とワイド (Unicode) の 2 つの関数のバージョンをエクスポートするものがあります。
このような場合に、CharSet を指定します。
例:
MessageBoxA ...ANSI
MessageBoxW ...Unicode
ExactSpellingプログラミング言語によって異なる。エントリ ポイントが文字セットに合わせて変更されることを防ぎます。
CallingConventionWinAPI メソッドに引数を渡すときに使われる呼び出し規約の値を指定します。
PreserveSigTrue (シグネチャの変換抑止)マネージ メソッド シグネチャが HRESULT を返すアンマネージ シグネチャに変換されることを抑止します。また、マネージ メソッド シグネチャが戻り値に [out, retval] 引数が追加される可能性があることを示します。
SetLastErrorFalse(C#, C++)
True(VB)
呼び出し元が Marshal.GetLastWin32Error API 関数を使って、メソッドの実行中にエラーが発生したかどうかを判断できるようにします。

5.プラットフォーム呼び出しのデータ型

Win32 API を呼び出すにあたり、引数の受け渡しが必要になりますが、これらのデータ型がちゃんとあっている必要があります。
データ型は次の表になりますが、詳細はMSDN を参照してください。

Wtypes.h に含まれるアンマネージ型アンマネージ C 言語型マネージ クラス名説明
HANDLE
void*System.IntPtr32 ビット
BYTEunsigned charSystem.Byte8 ビット
SHORTshortSystem.Int1616 ビット
WORDunsigned shortSystem.UInt1616 ビット
INTintSystem.Int3232 ビット
UINTunsigned intSystem.UInt3232 ビット
LONGlongSystem.Int3232 ビット
BOOLlongSystem.Int3232 ビット
DWORDunsigned longSystem.UInt3232 ビット
ULONGunsigned longSystem.UInt3232 ビット
CHARcharSystem.CharANSI により装飾。
LPSTRchar*System.String または System.StringBuilderANSI により装飾。
LPCSTRConst char*System.String または System.StringBuilderANSI により装飾。
LPWSTRwchar_t*System.String または System.StringBuilderUnicode により装飾。
LPCWSTRConst wchar_t*System.String または System.StringBuilderUnicode により装飾。
FLOATFloatSystem.Single32 ビット
DOUBLEDoubleSystem.Double64 ビット

注意
アンマネージコードから文字列が返される場合、System.String を使用すると String は変更不可(Imutable)なので、関数から戻ったときに、文字列がコピーされません。このため、アンマネージコードから文字列が返される場合は、次のように System.StringBuilder を使う必要があります。

6.文字列の受け渡し

文字列を渡す。
この場合は、System.String でOK。

[DllImport("kernel32.dll", EntryPoint="WritePrivateProfileString")]
private static extern uint WritePrivateProfileString( string lpApplicationName, string lpEntryName, string lpEntryString, string lpFileName );

WritePrivateProfileString( "SECTION", "ENTRY", str, "C:\\TEMP\\TEST.ini" );
文字列を受け取る。
文字列を受け取るためのバッファには、StringBuilder を使う必要があります。
というのは、string は、immutable (変更できない)ので、GetPrivateProfileStringからの文字列を受け取ることができないためです。
このために、StringBuilder を使って、バッファとして渡してあげる必要があります。

uint entryLength;
string strEntryStringValue;

[DllImport("kernel32.dll", EntryPoint="WritePrivateProfileString")]
System.Text.StringBuilder strEntryString = new System.Text.StringBuilder( 256 );
entryLength = GetPrivateProfileString( "SECTION", "ENTRY", "Nothing", strEntryString, (uint)(strEntryString.Capacity), "C:\\TEMP\\TEST.ini" );
strEntryStringValue = strEntryString.ToString();

7.改訂履歴

2003/5/31   初版作成