質問: ### 前提・実現したいこと C++ 初心者で、Unity 用 NativePlugin を制作しています。 対象プラットフォームは、Windows/Mac/Android/iOS であり、プラグインは C++ を利用して作っています。 一旦、Windows のものを作ろうと思い、Visual Studio で制作しています。コレクション関連を自前で実装するのは厳しいので、std::map や std::for_each を利用しています。 Visual Studio 上でテストアプリを作り、このプラグインの動作は確認済みです。 いざ、作成した dll を Unity 上で利用しようとすると、「std::map の count() で、そのキーが存在しているにもかかわらずカウントされない」とか、「std::for_each の処理に差し掛かったら落ちる」などあり、正常に動作しません。前述しました通り、Visual Studio 上でのテストアプリではこの処理は問題なく実行されています。 調べてみたところ、下記記事において「STL は使用してはならない」とあります。 ネイティブプラグイン開発のススメ (Unity/Cocos2dx) しかしながらコレクションを自前実装するのはスキル的に難しいので、なんとか使えればと思っています。 記事内には「ちょっと凝ったプラグインを作る場合は素直に STL を使って幾つかの STL バージョン用のバイナリを生成してます。」とあるので、何か回避策はあるのだろうと思うのですが、調べてみてもそういった内容の記事は見つからず、皆目見当がつきません。 ですので、下記の点をお尋ねしたいです。 * Windows/Mac/Android/iOS で扱う Unity プラグインにおいて、std::map や std::for_each を問題なく利用できる方法 * 難しい場合は、何か代替となるようなライブラリがあるか * そもそもそういう問題ではない場合、何が問題か 以上、よろしくお願いいたします。 ### 補足情報(FW/ツールのバージョンなど) Unity 2017.3.1p3 VisualStudio 2017
回答: Unityプラグイン(というかC#のDllImportで参照するDLL)の中でSTLを使うことには何の制限もありません。性能改善のためにC#アプリの処理の一部をC++で作るということは良くありますが、STLを使いまくっています。 > > 調べてみたところ、下記記事において「STL は使用してはならない」とあります。 > > > それは「Cocos2d-x」の文脈で語られていることですよね。Cocos2d-xはいじったことがないのでよく判りませんが、プラグインはスタティックライブラリー形式なのでしょうか。だとしたら、バージョン不整合は問題になります。 一方、Unity(というかC#)に関しては、DLLを動的リンクする方式なので、インターフェイス部分(関数プロトタイプ)さえきっちり決められていれば、中身をどう書こうと自由です。STLを使っても良いですし、boostのような外部ライブラリーを使っても何の問題もありません。たとえコンパイラーのバージョンが違っていても(基本的には)問題にはなりません。 ただし、C#のDllInportの場合「C形式の関数」しか対応していないので、引数にSTLコンテナを使うようなことはできません。それが制限といえば制限かもしれませんね。そのため、中身はクラスで実装するけど、C#向けにはC形式のラッパー関数を作ってそれをエクスポートする、ということをよくやります。 補足 ↑に書いた内容はWindowsのDLLの場合ですね。元記事をもう少し読み進めていったら、.soファイルとか書いてあるので、LinuxかMacということでしょう。となると、バージョン不整合は問題になるかもしれません。 まぁ、そうだとしても、コンパイラーのバージョンが変わったらリビルドすれば良いだけなので、STLを使ってはいけないという縛りをあえて設ける必要なないと思います。 追記 肝心なことを忘れていました。 > > いざ、作成した dll を Unity 上で利用しようとすると、「std::map の count() で、そのキーが存在しているにもかかわらずカウントされない」とか、「std::for_each の処理に差し掛かったら落ちる」などあり、正常に動作しません。 > > > テストアプリというのはC#で作ったのでしょうか? なるべく利用環境に近い状態でテストする必要があります エクスポート関数の引数などにコンテナが含まれていませんか? 前述の通り、C#のDllImportで呼べるのはC形式の関数のみです。 実際のところ、どのように作ってどのように呼んでいるのかが判らないので、なんとも答えようがありません。可能であればソースコードを提示していただければ、もう少し適切に回答できるかもしれません。