[C#] C# から C 言語の可変引数を持つ関数を呼ぶ

2014年4月12日

 C 言語の可変引数の関数を呼び出さなくてはならない場合、選択肢の一つとして、__arglist キーワードを使用する方法があるようです。

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

using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    class Program
    {
        [DllImport("msvcrt", CallingConvention = CallingConvention.Cdecl)]
        static extern int printf(string format, __arglist);

        static void Main(string[] args)
        {
            printf("%dn", __arglist(123));
            printf("%05d, %fn", __arglist(123, 456.78));
            printf("%2.3f, %sn", __arglist((double)12.345f, "abc"));
        }

    }
}

 とりあえず int や double(倍精度)、char*(文字列) は普通に通る模様。上記例では float(単精度) 直渡しはダメっぽかったので double で cast しています。

 ただ、この __arglist、非公式機能らしい。

 参考) .NETと安全なポインタ

 管理下ポインタによく似たものに、「型付けされた参照」がある。ボックス化を伴わずに、任意の型の値型を参照渡しできる、といえばその特徴が伝わるだろうか。型付けされた参照を利用すれば、正当性検証可能なsscanf関数(=C言語の文字列書式化関数。関数引数として複数の型を受け取れる)を実装することができる。

 とはいえ、型付けされた参照はCLS(共通言語仕様)準拠ではなく、今後C#で正式にサポートされる可能性も低い。大多数の人にとって、いままでもこれからも、型付けされた参照を目にする機会はないだろう。ただし、Visual C#には非公式キーワードとして__makeref、__refvalue、__arglistがあって、これらを使用すれば対応するILコードを出力することはできる。

 この説明によると、__arglist とは「ボックス化を伴わずに任意の型の値型を参照渡し」するもののようです。

 しかしこの機能、非公式機能ということからも多用は禁物ですね。どうしても C 言語側ライブラリのインターフェースが変えられない場合に限って使用するようにしたほうが無難な気がします。






カテゴリー: C#, Program, Visual C++

Follow comments via the RSS Feed | Leave a comment | Trackback URL

コメントを投稿する

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


«   »
 
Powered by Wordpress and MySQL. Theme by Shlomi Noach, openark.org