printfなどの可変引数を持つ関数はそのまま呼び出すことができないため、想定される引数を持つ関数をそれぞれ明示的に定義する必要があります。
CallingConvention Enumeration (System.Runtime.InteropServices) - MSDN
例えば、呼び出す対象の関数が次のように定義されているとすると、
int printf( const char *format [, argument]... )
C#のコードは次のようにします。
[DllImport( "msvcrt.dll", CallingConvention=CallingConvention.Cdecl )] public static extern int printf( String format, int i, double d );
[DllImport( "msvcrt.dll", CallingConvention=CallingConvention.Cdecl )] public static extern int printf( String format, int i, String s );
CallingConvention列挙体で、アンマネージド コードを呼び出すための呼び出し規約の指定をします。
| メンバ | 説明 |
|---|---|
| Cdecl | 呼び出し元がスタックを消去。可変引数のメソッドで使用する。 |
| StdCall | 呼び出し先がスタックを消去。 |
| ThisCall | 最初の引数がthisポインタ。アンマネージドDLLからエクスポートしたクラスのメソッドを呼び出すために使用する。 |
| Winapi | プラットフォームに応じた、既定の呼び出し規約を使用する。 (WindowsではStdCall、Windows CE.NETではCdecl) |
| FastCall | これはサポートされない。 |
__arglistキーワードを使用して可変引数を実現する方法もあります。
可変個の引数にパラメータを使用します - MSDN
[DllImport( "msvcrt", CallingConvention = CallingConvention.Cdecl )]
static extern int printf( string format, __arglist );
static void Main()
{
printf( "%d", __arglist( 123 ) );
printf( "%d, %f", __arglist( 123, 456.78 ) );
printf( "%d, %s", __arglist( 123, "abc" ) );
}
How do I call a C/C++ vararg function from .NET? - N/Direct - FAQ
va_list型の引数が書式制御のパラメータならば、vsprintf関数を使用してstring型に変換できます。
[DllImport( "msvcrt" )] static extern int vsprintf( byte[] str, string format, IntPtr args ); /// <param name="format">const char*型の書式制御文字列</param> /// <param name="args">va_list型の可変引数リストへのポインタ</param> static void Foo( string format, IntPtr args ) { byte[] str = new byte[ 0xFF ]; int count = vsprintf( str, format, args ); Console.Write( System.Text.Encoding.ASCII.GetString( str, 0, count ) ); }