第1章 はじめに
第2章 マーシャリング基礎
第3章 簡単なマーシャリング
第4章 構造体のマーシャリング
第5章 配列のマーシャリング
第6章 文字列の表現
第7章 文字列の変換
第8章 文字列のマーシャリング
第9章 上級マーシャリング
あとがき
この本を手に取っていただきありがとうございます。技術書典9に向けて作成した「Unityで使うC#/DLL マーシャリング事典」をベースに説明を加えたものです。ネイティブライブラリーを呼び出す際に必要になる「マーシャリング」について、Unity という条件を加えて説明した文献は非常に数が少ないか、現状この本が唯一となるのではないかと考えております。あなたのネイティブライブラリー呼び出しに悩む時間を、少しでも短縮できれば幸いです。
本書は以下に挙げるような読者を想定しています。
・Unity におけるマーシャリング入門者
・毎回マーシャリングのコード・記述に悩む方
・ちょっと複雑なマーシャリングで悩んでいる方
・マーシャリングについてまとまった情報を求めている方
・.NET Framework(CLR)とUnityのマーシャリングの差違に困っている方
多少の C/C++ の知識や、 Windows DLL に関する知識などを持っていると理解の助けになります。
ここで「いつ,なぜマーシャリングが必要になるのか」という問いがあります。Unity ではネイティブプラグインと呼ばれる DLL/so/dylib ファイルを呼び出して使用することができます。ネイティブプラグインは名前の通り、ネイティブで実装されています。ここでネイティブというのは、主に C/C++ やAndroidであればJavaを用いて実装されている(プラットフォームに合った実装)という意味合いです。これらの機能を呼び出す際にマネージドコードとネイティブコードの間でデータ型を変換するプロセス=「マーシャリング」が必要になります。
これが必要になる場面としては以下の状況が挙げられます。
・Unity が機能を公開していない何らかの機能を使いたいとき
・サードパーティー製のモジュールやライブラリーを、Unity で使いたい(しかし、Unity向けに提供はされていない)
・処理速度を求めて機能をネイティブ実装することになった場合
・Unity の GC の対象から逃れたい
いずれにしても標準の機能からは1歩先に進んだときに必要となってくるものでしょう。
この本は「マーシャリング」を取り扱ったものです。Unity でネイティブプラグインというと Android の Java によるネイティブプラグインも対象に含まれますが、この本ではそれを考慮しません。C/C++ で実装されたネイティブプラグインを対象とします。
ネイティブプラグインを扱うときのお作法についても本書ではほとんど触れません。この本では ネイティブプラグインの作り方ではなく、ネイティブプラグインの関数の呼び出し方がわかる、に限定されます。
ご存じの方もいると思いますが、unsafe ブロックを用いることで C# ではポインタをそのまま扱えます。しかし本書では可能な限り unsafe を使用せず、C#コードではポインタを出現させないことを趣旨にしております。またネイティブメソッドの呼び出し定義は NativeMethodsというスタティッククラスに定義したものとして話を進めております。
一般的に C# で実装したアプリケーションはコンパイラによって共通中間言語(Common Intermediate Language:CIL) にコンパイルされます1。マイクロソフトの .NET Framework では共通言語ランタイム(Common Language Runtime :CLR) によってコードが実行されます。
一方 Unity では、 CIL を実行するのは CLR ではありません。Mono もしくは IL2CPP という別のランタイムによって C# のコードが実行されます。
このような実行されるエンジンの違いにより動作の異なる部分が出てきます。Webを検索すると多くのマーシャリングに関連する情報が見つかりますが、この差違を考慮して読み解く必要があります。この本では「Unity C# から使ったときのマーシャリング」に焦点を当てて説明していきます。CLR でのマーシャリングに慣れている方にとっても新発見があるかもしれません。
本書は以下の動作環境を対象としています。場合により Android や iPhone を対象とする補足を行います。
・Unity 2019.4.12f1
・Windows10 64ビット
以下の環境については対象外としています。
・非Windows 環境での Unity エディターおよびスタンドアロン動作
この本に記載された内容は、情報の提供のみを目的としています。内容について注意を払って記述しておりますが、間違いなどが含まれている可能性もございます。したがって、書かれた情報(コード例を含む)を使用することで生じた結果に対して、著者及び出版社はいかなる責任も負いません。その点はあらかじめご了承ください。
・Mono / Interop with Native Libraries
─https://www.mono-project.com/docs/advanced/pinvoke/
・Microsoft / Charsets and marshaling
─https://docs.microsoft.com/en-us/dotnet/standard/native-interop/charset
・Microsoft / Native interoperability best practices
─https://docs.microsoft.com/en-us/dotnet/standard/native-interop/best-practices