昨年末にPrince of Percia: SOTをやって以来、全くPCゲームをプレイする気が失せていたのは前回書いたとおりである。 Painkillerも昔の面クリア型ゲームを中途半端に模したような感じでかなり興醒めというか期待外れだった。ところが、 ビデオカードのアップグレード予定も当分ないので今年はこのまま何もやらずに済まそうかなどと思っていたところ、あっさりと その方針を覆らせるゲームに当たってしまった。何のことはない、Unreal Tournament 2004である。デモ版をダウンロードして遊んでみたところ、ネットワーク対戦のOn-slaughtが実に面白い。デモ版でこれだけ遊べていいのだろうかという出来の良さに率直に驚いてしまった。
前作では、前々作からのグラフィックスの進歩にばかり目を取られ、時間もないということでUTで定評のあるボットの能力を信用してシングルプレイのラダーを クリアしあっさり通り過ぎていたのが、今作のONSで遅ればせながらやっとネットワーク対戦FPSの真価に触れたような気がする。グラフィックス上は前作からほとんど進歩しておらず、またキャラクターもほとんど使い回しという状態ではあっても、乗り物 が正式サポートされたことで遊びの幅が立体的に広がった。最近では乗り物が登場するFPSは珍しくないとはいえ、Unrealの世界の武器の扱いに慣れすぎているせいか、Halo等では味わえない絶妙のバランスを感じる。それも、Haloほどにはかっちりと した作りでもなく、Unrealという名の文字通り非現実的にキャラクターがぴょんぴょん跳び回りつつ激しく接近戦を行うというのがUnreal Tournamentの真骨頂だ。20分程度で済むONSは実にリプレイバリューが高く、たとえ負けても激しい抗戦ができればそれなりに満足感がある。その場限りの人間のチームは、上級者と下級者が混ざっているのでよりメリハリのあるプレイを楽しめる。ONS(とASの一部)では乗り物もあるので、1on1だとさかんにサイドステップで飛び回る上級プレイヤーを叩ける逆転のチャンスも増え、集団ゲームとして実に合理的なハンディキャップ配置である。PCのいわゆる洋ゲーしかやらず、UTではなくUnreal本編のようなシングルプレイヤー物を好み、一回最後までやったゲームは大概そのまま手放してしまう私のような人間にとって、この中毒性の陶酔は久々の感覚である。下手をすると一年間UT2004だけでゲームの欲求をまかなえそうな気すらしている。良作の太鼓判を押したい。
ただ、これだけ褒めちぎり甲斐のあるUT2004でも、弱点はある。それはシングルプレイにおけるボットのAIである。定評のあるUTのボットだが、今回ばかりは人間と対比しての部分で分が悪い。人間相手の対戦ばかりやっていると、ボットの挙動の機械的な限界と、人間のプレイヤーの人間的な癖や戦略的強さとの差異を、画面越しにひしひしと感じる。例えば、シングルプレイのラダーにONSは入っていないのでINSTANT ACTIONでONSをプレイしてみると、ボットは非常に合理的にリンクノードを攻めようとするか、あるいは異常に向こう見ずな先制特攻をかけてくるかの二つに一つである。ボットの技能を調節したときは、シングルプレイのラダーを上っていけば分かるよう に、チームプレイヤーの4つの能力パラメータ(正確さ/攻撃性/敏捷さ/戦略)がきちんと上昇していき、Skaarjの場合サイド ステップが多いなどのゲーム上の特徴を除くとほとんどむらがない。そして、上級ボットが恐ろしく武器の持ち替えが早いとか反応速度が速いとかいった形で強いのに対し、低級ボットは妙に動作が遅く照準も定まらないといったようなわかりやすい差が、 ONSに比べゲームの密度の濃い1on1の戦闘ですら時折気になる。ところが、人間の上級プレイヤーの場合は、抽象的な表現をす れば、反射ではなく先読みが異常に優れている。それは、人間のプレイヤーの癖を学習しないと得られない戦略であり、残念ながら製品版でもそういった観点のボット強化はあまり行われなかったようである。結果的に、ONSのシングルプレイは非常に味気ないものになっている。もちろん裏を返せばそれだけネットワーク対戦が魅力的であるということになる。
具体的な人間プレイヤーの挙動としては、ネットワーク対戦を観察していて最も人間的に感じたのは、Mantaで相手の頭上高く跳ねてそのままほぼ垂直降下し相手を潰すテクニックである。真上という、マウスで回す場合視界が最も及びにくいと思われる方向から攻撃を仕掛け人間のプレイヤーが最も嫌う死角を突くというこの戦略は、ボットにあらかじめ組み込めば可能なのだろうが、それにしても実に人間的である。車のクラクションを鳴らして味方を拾うのも些細なことだが協力プレイの基本コミュニケーションだ。またマップの特性を理解した上で、リンクノードを移動せずに超長距離から乗り物で砲撃するのもボットにはない人間プレイヤーの常套手段だろう。こうしてみると、相手の人間的な癖を読んだ戦略の効用を自分も理解できゲーム内の世界で学習していくという感覚を覚えた ときこそが、ネットワークFPSの真髄を直感する瞬間と言えはしないだろうか。これは、同じネットワークゲームでも、MMORPGの世界とはおそらく異質な、あるいはもっと鮮烈な体験である。会話は罵声と"pwnage""gg"等々以外ほとんど欠くネットワークFPSでは、侍の世界よろしく、プレイヤーが無言の対話を丁々発止の決闘の最中に交わしているのだ。 そうはいっても負けたときにはそれなりに腹立たしさも感じるのでついつい勝つまで繰り返すこともある。それでも、ボットのチームに理不尽な負け方をした時ほどの屈辱感はないのが不思議だ。近い将来もっと賢いAIがボットに搭載され人間プレイヤーとの区別が付かない程度まで進歩するとしたら、この感覚がどのように変容するのか、非常に興味深い。
今回のバージョン0.84からDICEのHTTPサーバ部分に、.NETアプリケーションコンテナと称して、.NETオブジェクトをホ スト出来 るようにした。C#/VB.NET/JScriptのコードをアセンブリにコンパイルして実行する機能と、.NETアセンブリを直接実行する機能がある(ただしエントリポイントはMainではなくて特定の抽象クラスをユーザに実装してもらう方式)。リース期間はデフォルトで無限なので、CGIとは違 いISAPIのようにメモリ上に置きっぱなしになり、PHPやJ2EEのようなセッション管理も可能である(ユーザがコードを書きさえすれば)。ただしメ モリはそれなりに食うようである。ひょっとしたらリークしているのかもしれないが、CLRだかCOMマーシャリングだかのキャッシュはある程度呼び出しを繰り返すと落ち着くようだ。折角のWebサーバ機能にも関わらずCGIのようなダイナミックコンテンツをまったくサポートしないのはさすがに格好悪いよねということで色々考えていたところ、一番簡単そうなのがこれということで.NETを対象にすることになった。本当はASP.NETがサポートできれば大した話なんだろうが、さすがにそこまで大仰な物は作れないので、自分でC#やVB.NETのコードを書いたりコンポーネントを利用したりする人がプログラマ ブルに使えればいいだろうということでこの形にした。現在のASP.NETや、将来のYukonのストアドプロシージャ同様に、Unmanagedコード 内にCLRをホストし、そこで.NETのオブジェクトを動かすという仕組みである。今のところセキュリティもへったくれもないのでサーバ管理者自身が好き放題に書いたスクリプトを実行するという使い方を想定している。いずれにせよWindows XP SP2でHTTP.SYSが搭載されるとのことなのでパフォーマンスの点ではIISに対抗しても仕方ない。Perl、PHP、Rubyなどがサポートできれば既存のCGIスクリプトの再利用という観点からは最良なのだけれど、PerlはActiveStateのdllが関係しそうだしPHPも Rubyも個人的に興味ないしで(CGIが使っている標準出力とかフックするのは大変そうだしRubyの組み込みマニュアルは本当にスカスカだし)、かと いってApacheモジュールを使えるようにするとかいった計画は遊びには面倒すぎる。そこで.NETアプリケーションサーバという名目で行くことになった。世に出ているJavaのアプリケーションサーバは大概自前のJavaの実装を持っているようだけれど.NET系のものはどうなっているのだろうか。
一応DICEは今となってはやや古いWindows 2000も対象としているので、あまり.NET Frameworkには触れずに済ませ、次に作るアプリケーションで色々新しい構成を考えようと従来思っていたけれども、ある問題についてなかなか良い解がないので思いあぐね、DICEの方に一つの関連する方法を実装してみて具合を見ようというのも今回の追加機能の目的の一つである。その問題というのは、UnmanagedアプリケーションとManagedアセンブリの通信チャネルの選択である。それも、双方向で非同期の通信を可能にしたい。今回の場合で 言うと、.NETコンポーネント側から見るとUnmanagedのDICEから非同期に呼び出しが来るように見えても、ホストされている.NETコンポー ネントが非同期にDICEを呼び出す手段は提供していない。今のところ、DICEがホストしている.NETオブジェクトから非同期にDICEを呼ぶには、DICEにCOMのインターフェイスをつけて登録するのが簡単そうではある(既にATLサービスなのでレジストリも使っている)が、どうもスマートでない気がする。大体、ホストしている.NETコンポーネントの方へデバッガを仕掛けることがどうやら現状のDICEでは不可能なので、テストユニットを使ってドライバを用意したりする暇もない状況ではかなり面倒である。最近VC++ 7.1が無料配布されることになったが、やはりVCの肝はデバッガで、それが抜けていると少なくとも開発には役に立たない。Unmanaged/Managedの一番大袈裟な通信方法はおそらくMSMQやCOM+を使うものでこれはプラットフォームに依存しすぎる嫌いがある。そこで、以前は、TCP/IP接続が、低レベルながら移植性が高い上に位置透過性もあり最善と考えていたが、プロトコルを一々実装するのはやはり面倒は面倒だ。
最近は、上述のデバッガ問題から、Unmanaged C++にしがみつくのはやめにして、Managed C++でラッパーを作ってアプリケーション自体はいい加減に.NETの方へ重点を移し、位置透過性は.NETリモーティングでどうにかするのがいいかもと考えている。それなら、さすがにデバッガも問題なく使えるはずだ。そのためには、今使っているC/C++のライブラリをどうにかする必要が出てきそうで、 これもなかなか頭が痛い。DICEのために作ったフレームワークも、次にそのまま使うというわけにはいかない。とはいっても、もう私の中では腹は決まって いる。今回のDICEのようにC++で作った部分はピュアなUnmanaged実行ファイルとして保ち分離されたManagedアセンブリと通信させるモデルは、個人の立場ではこれ以上の維持は無理だというのが私の結論である。それよりは、パフォーマンスは要求しないアプリケーションの動作部分やGUIはC#で書き、パフォーマンスを要求する部分やレガシーコードをUnmanaged C/C++のコードをManaged C++でラップして、それらを一つのアプリケーションとして綴じ込むべきで、同期だの非同期だのといったことはマシン内では忘れた方が良い。実に単純な話 だが、C++テンプレートのテクニックやパフォーマンスハックなどC++の楽しさに拘泥しすぎて完全な宗旨替えがいささか遅れてしまったようである。
DICEで一番デバッグに時間がかかったのはパースレッドメモリアロケータの部分だが、皮肉にも、それに次いで長い時間をSTLportの バグによって起こる、デバッガで追い切れない原因不明のメモリ破壊などの問題で失った。VC++ 7.1対応とバグ回避のためにCVSスナップショットを使用し始めたところ、そこに別のバグがあり、貴重な時間を随分失うことになってしまった。しかも更新 の度に別の新しいバグをコミットしてくれたりするので参った。最近になってCVS内のテストコードが充実し安定してきたからよかったものの、0.83のリ リースから0.84まで5か月近くもかかってしまったのはSTLportのCVSの更新を待っていたのが主な原因である。0.83は実は重要な問題を抱えていたにもかかわらず、足踏みする羽目になった。DICE 0.83使用者には、早期の入れ替えをお勧めする。.NETアプリケーションコンテナは、その期間の開きに対して埋め合わせとして、また上記の実験のため に入れたまでだ。これがパフォーマンスクリティカルな部分のみUnmanagedコードで、かつアプリケーションの他ライブラリ依存がもっと低ければ、こ んな苦労をせずに済んだことだろうと思う。STLportがオープンソースなのは不幸中の幸いである。.NETの場合で不安なのはマイクロソフトのライブラリにバグがあっても修正がなかなか得られないことくらいだ。ネイティブコードの世界ですら、最近プログラミング言語Dが 以前より大きな注目を集めるなど、確実に流れは新しい次元へ、それも以前よりさらに速く向かいつつある。.NETは登場以降3年経って全然普及していない などと言われるが、Longhornを前にして、ギアは一段上がった。コミュニティとレガシーコード群の大きさを除けば、C/C++は、そこでは明確に不利な、格下の存在だ。よくても、UnmanagedとManagedを繋ぐグルーコードの扱いである。
前作では、前々作からのグラフィックスの進歩にばかり目を取られ、時間もないということでUTで定評のあるボットの能力を信用してシングルプレイのラダーを クリアしあっさり通り過ぎていたのが、今作のONSで遅ればせながらやっとネットワーク対戦FPSの真価に触れたような気がする。グラフィックス上は前作からほとんど進歩しておらず、またキャラクターもほとんど使い回しという状態ではあっても、乗り物 が正式サポートされたことで遊びの幅が立体的に広がった。最近では乗り物が登場するFPSは珍しくないとはいえ、Unrealの世界の武器の扱いに慣れすぎているせいか、Halo等では味わえない絶妙のバランスを感じる。それも、Haloほどにはかっちりと した作りでもなく、Unrealという名の文字通り非現実的にキャラクターがぴょんぴょん跳び回りつつ激しく接近戦を行うというのがUnreal Tournamentの真骨頂だ。20分程度で済むONSは実にリプレイバリューが高く、たとえ負けても激しい抗戦ができればそれなりに満足感がある。その場限りの人間のチームは、上級者と下級者が混ざっているのでよりメリハリのあるプレイを楽しめる。ONS(とASの一部)では乗り物もあるので、1on1だとさかんにサイドステップで飛び回る上級プレイヤーを叩ける逆転のチャンスも増え、集団ゲームとして実に合理的なハンディキャップ配置である。PCのいわゆる洋ゲーしかやらず、UTではなくUnreal本編のようなシングルプレイヤー物を好み、一回最後までやったゲームは大概そのまま手放してしまう私のような人間にとって、この中毒性の陶酔は久々の感覚である。下手をすると一年間UT2004だけでゲームの欲求をまかなえそうな気すらしている。良作の太鼓判を押したい。
ただ、これだけ褒めちぎり甲斐のあるUT2004でも、弱点はある。それはシングルプレイにおけるボットのAIである。定評のあるUTのボットだが、今回ばかりは人間と対比しての部分で分が悪い。人間相手の対戦ばかりやっていると、ボットの挙動の機械的な限界と、人間のプレイヤーの人間的な癖や戦略的強さとの差異を、画面越しにひしひしと感じる。例えば、シングルプレイのラダーにONSは入っていないのでINSTANT ACTIONでONSをプレイしてみると、ボットは非常に合理的にリンクノードを攻めようとするか、あるいは異常に向こう見ずな先制特攻をかけてくるかの二つに一つである。ボットの技能を調節したときは、シングルプレイのラダーを上っていけば分かるよう に、チームプレイヤーの4つの能力パラメータ(正確さ/攻撃性/敏捷さ/戦略)がきちんと上昇していき、Skaarjの場合サイド ステップが多いなどのゲーム上の特徴を除くとほとんどむらがない。そして、上級ボットが恐ろしく武器の持ち替えが早いとか反応速度が速いとかいった形で強いのに対し、低級ボットは妙に動作が遅く照準も定まらないといったようなわかりやすい差が、 ONSに比べゲームの密度の濃い1on1の戦闘ですら時折気になる。ところが、人間の上級プレイヤーの場合は、抽象的な表現をす れば、反射ではなく先読みが異常に優れている。それは、人間のプレイヤーの癖を学習しないと得られない戦略であり、残念ながら製品版でもそういった観点のボット強化はあまり行われなかったようである。結果的に、ONSのシングルプレイは非常に味気ないものになっている。もちろん裏を返せばそれだけネットワーク対戦が魅力的であるということになる。
具体的な人間プレイヤーの挙動としては、ネットワーク対戦を観察していて最も人間的に感じたのは、Mantaで相手の頭上高く跳ねてそのままほぼ垂直降下し相手を潰すテクニックである。真上という、マウスで回す場合視界が最も及びにくいと思われる方向から攻撃を仕掛け人間のプレイヤーが最も嫌う死角を突くというこの戦略は、ボットにあらかじめ組み込めば可能なのだろうが、それにしても実に人間的である。車のクラクションを鳴らして味方を拾うのも些細なことだが協力プレイの基本コミュニケーションだ。またマップの特性を理解した上で、リンクノードを移動せずに超長距離から乗り物で砲撃するのもボットにはない人間プレイヤーの常套手段だろう。こうしてみると、相手の人間的な癖を読んだ戦略の効用を自分も理解できゲーム内の世界で学習していくという感覚を覚えた ときこそが、ネットワークFPSの真髄を直感する瞬間と言えはしないだろうか。これは、同じネットワークゲームでも、MMORPGの世界とはおそらく異質な、あるいはもっと鮮烈な体験である。会話は罵声と"pwnage""gg"等々以外ほとんど欠くネットワークFPSでは、侍の世界よろしく、プレイヤーが無言の対話を丁々発止の決闘の最中に交わしているのだ。 そうはいっても負けたときにはそれなりに腹立たしさも感じるのでついつい勝つまで繰り返すこともある。それでも、ボットのチームに理不尽な負け方をした時ほどの屈辱感はないのが不思議だ。近い将来もっと賢いAIがボットに搭載され人間プレイヤーとの区別が付かない程度まで進歩するとしたら、この感覚がどのように変容するのか、非常に興味深い。
今回のバージョン0.84からDICEのHTTPサーバ部分に、.NETアプリケーションコンテナと称して、.NETオブジェクトをホ スト出来 るようにした。C#/VB.NET/JScriptのコードをアセンブリにコンパイルして実行する機能と、.NETアセンブリを直接実行する機能がある(ただしエントリポイントはMainではなくて特定の抽象クラスをユーザに実装してもらう方式)。リース期間はデフォルトで無限なので、CGIとは違 いISAPIのようにメモリ上に置きっぱなしになり、PHPやJ2EEのようなセッション管理も可能である(ユーザがコードを書きさえすれば)。ただしメ モリはそれなりに食うようである。ひょっとしたらリークしているのかもしれないが、CLRだかCOMマーシャリングだかのキャッシュはある程度呼び出しを繰り返すと落ち着くようだ。折角のWebサーバ機能にも関わらずCGIのようなダイナミックコンテンツをまったくサポートしないのはさすがに格好悪いよねということで色々考えていたところ、一番簡単そうなのがこれということで.NETを対象にすることになった。本当はASP.NETがサポートできれば大した話なんだろうが、さすがにそこまで大仰な物は作れないので、自分でC#やVB.NETのコードを書いたりコンポーネントを利用したりする人がプログラマ ブルに使えればいいだろうということでこの形にした。現在のASP.NETや、将来のYukonのストアドプロシージャ同様に、Unmanagedコード 内にCLRをホストし、そこで.NETのオブジェクトを動かすという仕組みである。今のところセキュリティもへったくれもないのでサーバ管理者自身が好き放題に書いたスクリプトを実行するという使い方を想定している。いずれにせよWindows XP SP2でHTTP.SYSが搭載されるとのことなのでパフォーマンスの点ではIISに対抗しても仕方ない。Perl、PHP、Rubyなどがサポートできれば既存のCGIスクリプトの再利用という観点からは最良なのだけれど、PerlはActiveStateのdllが関係しそうだしPHPも Rubyも個人的に興味ないしで(CGIが使っている標準出力とかフックするのは大変そうだしRubyの組み込みマニュアルは本当にスカスカだし)、かと いってApacheモジュールを使えるようにするとかいった計画は遊びには面倒すぎる。そこで.NETアプリケーションサーバという名目で行くことになった。世に出ているJavaのアプリケーションサーバは大概自前のJavaの実装を持っているようだけれど.NET系のものはどうなっているのだろうか。
一応DICEは今となってはやや古いWindows 2000も対象としているので、あまり.NET Frameworkには触れずに済ませ、次に作るアプリケーションで色々新しい構成を考えようと従来思っていたけれども、ある問題についてなかなか良い解がないので思いあぐね、DICEの方に一つの関連する方法を実装してみて具合を見ようというのも今回の追加機能の目的の一つである。その問題というのは、UnmanagedアプリケーションとManagedアセンブリの通信チャネルの選択である。それも、双方向で非同期の通信を可能にしたい。今回の場合で 言うと、.NETコンポーネント側から見るとUnmanagedのDICEから非同期に呼び出しが来るように見えても、ホストされている.NETコンポー ネントが非同期にDICEを呼び出す手段は提供していない。今のところ、DICEがホストしている.NETオブジェクトから非同期にDICEを呼ぶには、DICEにCOMのインターフェイスをつけて登録するのが簡単そうではある(既にATLサービスなのでレジストリも使っている)が、どうもスマートでない気がする。大体、ホストしている.NETコンポーネントの方へデバッガを仕掛けることがどうやら現状のDICEでは不可能なので、テストユニットを使ってドライバを用意したりする暇もない状況ではかなり面倒である。最近VC++ 7.1が無料配布されることになったが、やはりVCの肝はデバッガで、それが抜けていると少なくとも開発には役に立たない。Unmanaged/Managedの一番大袈裟な通信方法はおそらくMSMQやCOM+を使うものでこれはプラットフォームに依存しすぎる嫌いがある。そこで、以前は、TCP/IP接続が、低レベルながら移植性が高い上に位置透過性もあり最善と考えていたが、プロトコルを一々実装するのはやはり面倒は面倒だ。
最近は、上述のデバッガ問題から、Unmanaged C++にしがみつくのはやめにして、Managed C++でラッパーを作ってアプリケーション自体はいい加減に.NETの方へ重点を移し、位置透過性は.NETリモーティングでどうにかするのがいいかもと考えている。それなら、さすがにデバッガも問題なく使えるはずだ。そのためには、今使っているC/C++のライブラリをどうにかする必要が出てきそうで、 これもなかなか頭が痛い。DICEのために作ったフレームワークも、次にそのまま使うというわけにはいかない。とはいっても、もう私の中では腹は決まって いる。今回のDICEのようにC++で作った部分はピュアなUnmanaged実行ファイルとして保ち分離されたManagedアセンブリと通信させるモデルは、個人の立場ではこれ以上の維持は無理だというのが私の結論である。それよりは、パフォーマンスは要求しないアプリケーションの動作部分やGUIはC#で書き、パフォーマンスを要求する部分やレガシーコードをUnmanaged C/C++のコードをManaged C++でラップして、それらを一つのアプリケーションとして綴じ込むべきで、同期だの非同期だのといったことはマシン内では忘れた方が良い。実に単純な話 だが、C++テンプレートのテクニックやパフォーマンスハックなどC++の楽しさに拘泥しすぎて完全な宗旨替えがいささか遅れてしまったようである。
DICEで一番デバッグに時間がかかったのはパースレッドメモリアロケータの部分だが、皮肉にも、それに次いで長い時間をSTLportの バグによって起こる、デバッガで追い切れない原因不明のメモリ破壊などの問題で失った。VC++ 7.1対応とバグ回避のためにCVSスナップショットを使用し始めたところ、そこに別のバグがあり、貴重な時間を随分失うことになってしまった。しかも更新 の度に別の新しいバグをコミットしてくれたりするので参った。最近になってCVS内のテストコードが充実し安定してきたからよかったものの、0.83のリ リースから0.84まで5か月近くもかかってしまったのはSTLportのCVSの更新を待っていたのが主な原因である。0.83は実は重要な問題を抱えていたにもかかわらず、足踏みする羽目になった。DICE 0.83使用者には、早期の入れ替えをお勧めする。.NETアプリケーションコンテナは、その期間の開きに対して埋め合わせとして、また上記の実験のため に入れたまでだ。これがパフォーマンスクリティカルな部分のみUnmanagedコードで、かつアプリケーションの他ライブラリ依存がもっと低ければ、こ んな苦労をせずに済んだことだろうと思う。STLportがオープンソースなのは不幸中の幸いである。.NETの場合で不安なのはマイクロソフトのライブラリにバグがあっても修正がなかなか得られないことくらいだ。ネイティブコードの世界ですら、最近プログラミング言語Dが 以前より大きな注目を集めるなど、確実に流れは新しい次元へ、それも以前よりさらに速く向かいつつある。.NETは登場以降3年経って全然普及していない などと言われるが、Longhornを前にして、ギアは一段上がった。コミュニティとレガシーコード群の大きさを除けば、C/C++は、そこでは明確に不利な、格下の存在だ。よくても、UnmanagedとManagedを繋ぐグルーコードの扱いである。
コメント
コメントを投稿