更新日から1年以上経過しています。情報が古い可能性がございます。
概要
MagicLeap Extension for VSCode を使った MagicLeap で利用可能な Shared Libraryを作成する方法。
Templateから作成すると、そのままではMagicLeapで動作しないので、その解決方法を述べる。
Templateからプロジェクトを作成する
まずはじめにこの記事の執筆時点での各種バージョンを記載します。
- OS : Windows 10 Home (Build 19041.21)
- VSCode : 1.14.1
- MagicLeap Extention for VSCode : 0.9.10
- Lumin OS : 0.98.01
- Lumin SDK : 0.23.0
- IDE : VisualStudio2019 Community
- Unity : 2019.2.19f1
さて、バージョンを書いたところで本題へと移っていきます。
MagicLeap Extention for VSCodeをインストールすると、VSCodeのメニューにMagicLeapのアイコンが表示されます。
ここから幾つかの mabu の Example と、プロジェクトのテンプレートが生成できます。
ではリストから Shared Library Project Template を選び、右クリックを押し、Create project from template を選んでいきましょう。プロジェクトの名前を聞かれるので、今回は Sampleという名前で作成しました。この名前は生成される Shared Library の名称にも使われます。
生成されたプロジェクトは以下のような構成になっています
。
Sample
├ .vscode/
│ ├ launch.json
│ ├ settings.json
│ └ tasks.json
├ inc/
│ └ Sample.h
├ src/
│ └ Sample.cpp
└ Sample.mabu
VisualStudio2019用の設定
私の使っているのは VisualStudio2019 ですが、デフォルトのビルド設定は VisualStudio2017 用になっています。2017で良い方はここは読み飛ばしてください。
さて、このプロジェクトをVSCodeで開くと、上部メニューの Terminal のところに 「Run Build Task…」というものが追加されており、そこから Lumin OS 用のビルド、Host OS 用のビルドが選べるようになっております。
私の環境には VisualStudio2017は入っていないので、そのまま Host OS 用のビルドをすると、コンパイラが入っていない旨のエラーを出してビルドができません。
mabu: using build target 'debug_win_msvc-2017-15.0_x64'
mabu: error: No Visual Studio installation could be found for toolchain msvc-2017-15.0
The terminal process terminated with exit code: 1
そこで tasks.json を書き換え、VisualStudio2019 のコンパイラを使うようにします。
task.json から以下の部分を探します。
{
"label": "Build (Host OS Debug)",
"type": "shell",
"command": "${config:lumin_sdk}/mabu",
"windows": {
"command": "${config:lumin_sdk}/mabu.cmd",
"options": {
"env": {
"VisualStudioVersion": "15.0"
}
}
},
"args": [
"${workspaceFolder}/${config:lumin_mabu_file}",
"-t",
"host_debug",
"-j8"
],
"group": "build",
"problemMatcher": [
"$msCompile",
"$gcc"
]
},
こちらは Debug Build 用の設定です。同様のものが Release Build 向けにもあるので、そちらにも同じ変更を行ってください。
変更する箇所は、
"options": {
"env": {
"VisualStudioVersion": "15.0"
}
}
の、”15.0″の部分です。VisualStudio2019は16になるので、”16″に変更します。執筆時点のバージョンは16.4なのですが、小数点以下は省略しても大丈夫でした。
変更後にビルドを行うと無事に成功します。
mabu: warning: mabu does not recognize this version of Visual Studio yet (16)
mabu: using build target 'debug_win_msvc-2019-16.4_x64'
[Sample] Compiling Sample.cpp...
Sample.cpp
[Sample] Linking DLL Sample.dll...
mabu: 'Sample' output in '.out\debug_win_msvc-2019-16.4_x64'
足し算のライブラリ
ではコードを書いていきましょう。Sample.h と Sample.cpp に以下の関数を書いてみます。
#include "Sample.h"
int Add(int a, int b) {
return a + b;
}
// Sample.h
#ifdef _WIN32
#define UNITYEXPORT __declspec(dllexport)
#else
#define UNITYEXPORT
#endif
#include <stdio.h>
extern "C" {
UNITYEXPORT int Add(int, int);
}
UNITYEXPORT __declspec(dllexport) の部分は、Windows 用にビルドした時だけ必要になるものを、プリプロセッサディレクティブで制御しています。
こちらは、エディター上で動かす際にも必要になります。
ではビルドしていきましょう。
Editor上で確認する用の Host OS Build と、Lumin OS Build の2種類を用意します。
ビルドすると Sample.dll と libSample.so ができているはずです。ではそれを unity 内の Plugins ディレクトリに入れておきましょう。また、ライブラリのプラットフォームも設定しておきます。
Sample.dll は Lumin 以外にチェックを、libSample.so は Lumin にのみチェックを入れておきます。
プロジェクトにライブラリを入れたら次はそれを使用するスクリプトを書いていきます。
以下のURLを参考に、AddTest.cs を用意しました。
https://developer.magicleap.com/learn/guides/sdk-build-native-plugins-for-magic-leap-on-unity
using System.Runtime.InteropServices;
using UnityEngine;
public class AddTest : MonoBehaviour
{
[DllImport("Sample", CallingConvention = CallingConvention.Cdecl)]
private static extern int Add(int a, int b);
void Start()
{
Debug.Log(Add(3, 4));
}
}
このスクリプトを Scene の Camera にでも貼り付けて実行してみましょう。
7
UnityEngine.Debug:Log(Object)
AddTest:Start() (at Assets/Scripts/AddTest.cs:12)
無事に Editor 上で動くことが確認できました。
続いて MagicLeap にビルドして入れて実行します。
結果は The Lab の Log から確認します。
Error;Unity;DllNotFoundException: Unable to load DLL 'Sample': The specified module could not be found.;
なんということでしょう!DllNotFoundException が出ています!Editor では動いたのに!
MagicLeapで動かす
なぜ動かないのかと言うと、mabu の OPTIONS に問題があります。問題の Sample.mabu を見てみましょう。
KIND = shared
SRCS = src/Sample.cpp
INCS = inc/
USES = ml_sdk
OPTIONS = \
standard-c++/11 \
stl/libgnustl
これを見て、Android での開発に慣れている人は気付いたかもしれません。
問題のある部分は「stl/libgnustl」です。
Android NDK r18 から libgnustl はビルドパッケージに同梱されなくなりました。それを指定しているためエラーが出ています。
https://gitlab.freedesktop.org/ystreet/cerbero/commit/42f4209abdbc544a615957be48da3af70bf7734f
公式の Extension から作ったのに!なんということでしょう!!
では代わりに何を使うかというと、「libc++」です。
https://developer.android.com/ndk/guides/cpp-support
変更した Sample.mabu は以下のようになります。
KIND = shared
SRCS = src/Sample.cpp
INCS = inc/
USES = ml_sdk
OPTIONS = \
standard-c++/11 \
stl/libc++
こちらを再度ビルドして MagicLeap に入れて実行してみます。
Info;Unity;7;
無事にログが出力されています。成功です!
ちなみに、.mabu に指定可能なオプションはコンポーネントは、以下のディレクトリを見ると分かります。
{MLSDK}\tools\mabu\data
最後に
MagicLeap は面白いデバイスではありますが、なかなかこう、用意されている API がまだまだ機能不足です。そこで C/C++ で自前でライブラリを用意してしまえ、となるわけです。
さあみんなもガンガンライブラリを開発して、もっと MagicLeap を使い易くしていきましょう!