可変引数をパラメータに持つC++の関数を、C#から利用する方法

printfなどの可変引数を持つ関数は、そのまま呼び出すことはできません。

複数の関数を宣言する

想定される引数を持つ関数を、それぞれ宣言します。CallingConvention Enumeration (System.Runtime.InteropServices) | MSDN

たとえば呼び出す対象の関数が、

int printf( const char *format [, argument]... )

のように定義されているとすると、C#のコードでは次のように記述します。

  • 引数にintとdoubleが渡されることを想定した関数
    [DllImport( "msvcrt.dll", CallingConvention=CallingConvention.Cdecl )]
    public static extern int printf( String format, int i, double d );
    
  • 引数にintとStringが渡されることを想定した関数
    [DllImport( "msvcrt.dll", CallingConvention=CallingConvention.Cdecl )]
    public static extern int printf( String format, int i, String s );
    

__arglistキーワードで宣言する

__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型

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 Method( 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 ) );
}
Microsoft Learnから検索