GomobileからAndroidでマルチスレッドしてみる


今回はgomobile+unityでGoroutineを実装できるか試した編。
結果は、JAR経由でGomobileで作成したAARは動くことが確認できたが、直接Shared Libraryを動かすまでは行けていない。

## cgoで書いたShared LibraryをUnityから直接コールはダメですか？

何となく今回は返り値をstringで実装してみた。
Stringで実装する場合、Unityとcgoでは値の受け渡しの調整が必要になる。
C.CStringでラップするのとC.freeで解放は忘れてはいけない。
しかし、プログラムを実装したがスレッド実行時にハングして終わる結果となる。

コマンド

```
GOMOBILE=$GOPATH/pkg/gomobile \
GOOS=android \
GOARCH=arm \
NDK=ndk-r12b \
CC=$GOMOBILE/android-${NDK}/arm/bin/arm-linux-androideabi-clang \
CXX=$GOMOBILE/android-${NDK}/arm/bin/arm-linux-androideabi-clang++ \
CGO_CFLAGS="-target armv7a-none-linux-androideabi --sysroot $GOMOBILE/android-${NDK}/arm/sysroot" \
CGO_CPPFLAGS="-target armv7a-none-linux-androideabi --sysroot $GOMOBILE/android-${NDK}/arm/sysroot" \
CGO_LDFLAGS="-target armv7a-none-linux-androideabi --sysroot $GOMOBILE/android-${NDK}/arm/sysroot" \
CGO_ENABLED=1 GOARM=7 go build -pkgdir=$GOMOBILE/pkg_android_arm \
-tags="" -x -buildmode=c-shared \
-o=./hoge/libhoge.so \
hoge.go
```

cgoで思ったのはgoの書き方からだいぶ変わるのでこの書き方で実装すべきかどうかという点

```go:hoge.ho
package main

import (
  "fmt"
)

// #include <stdlib.h>
import "C"
import "unsafe"

//export MyFunction
func MyFunction() *C.char {

    co := make(chan string)
    hello(co)

    msg := fmt.Sprintln(<-co, "World")
    msg += fmt.Sprintln("Hello", <-co)
    msg += fmt.Sprintln(<-co)

    p := C.CString(msg)
    defer C.free(unsafe.Pointer(p))
    return p
}

func hello(yield chan<- string) {
    go func() {
        yield <- "Hello"
        yield <- "Gopher"
        yield <- "Hello NDS"
    }()
}

func main() {
}
```

```csharp:ButtonTest.cs
using UnityEngine;
using System.Runtime.InteropServices;

public class ButtonTest : MonoBehaviour {

	string msg;

	[DllImport("hoge")]
	private static extern string MyFunction();

	public void TestClick()
	{
		string str = MyFunction();
		Debug.Log(str);
		msg = str;
	}

	void OnGUI(){
		GUI.Label (new Rect (0, 0, 300, 300), msg );
	}
}
```

何かお作法があるのだろうか？もう少し勉強してみます。
今後に期待。


## Gomobile標準のbindで作ったAARをばらしてShared LibraryだけをUnityで動かす

これはStringの返り値をC.CStringで実装してないので動くはずもないのでスルー。

## Gomobileで作成したAARをJAR経由で実行する

このやり方だとGoroutineは動いた。
JAR経由と書いてあるが、AARの内部でclasses.jarが入っており、それをコールしてるということ（ややこしい）

![callimage.png](https://qiita-image-store.s3.amazonaws.com/0/35973/83503b63-4fd3-66ae-9720-43003414f717.png)

Unity -> AAR -> AAR(Classes.jar -> libgojni.so) の順でコールしている。

```go:hoge.go
package hoge 

import (
    "fmt"
)

func MyFunction() string {

    co := make(chan string)
    hello(co)

    msg := fmt.Sprintln(<-co, "World")
    msg += fmt.Sprintln("Hello", <-co)
    msg += fmt.Sprintln(<-co)
    return msg
}

func hello(yield chan<- string) {
    go func() {
        yield <- "Hello"
        yield <- "Gopher"
        yield <- "Hello NDS"
    }()
}
```

Gomobile標準のbindコマンドで`hoge.aar`を出力

```
$ gomobile bind -target=android .
```

Android StudioのAndroidLibraryのlibsにhoge.aarをセットする。

![andtoidfolder.png](https://qiita-image-store.s3.amazonaws.com/0/35973/d1ac2b46-7e82-3dee-153d-6545ab6f9dbb.png "andtoidfolder.png")


```java:HogeClass.java
package com.example.manabu.hogedroid;
import go.hoge.Hoge;

public class HogeClass {
    public static String get(){
        return Hoge.myFunction();
    }
}
```
```csharp:ButtonTest.cs

using UnityEngine;
using System.Collections;

public class ButtonTest : MonoBehaviour
{

	string msg = "";

	public void TestClick(){
		#if UNITY_ANDROID

		using (AndroidJavaClass jc = new AndroidJavaClass("com.example.manabu.hogedroid.HogeClass"))
		{
			Debug.Log(jc);
			string msg = jc.CallStatic<string>("get");
			Debug.Log(msg);
		}
		#endif
	}

	void OnGUI(){
		GUI.Label (new Rect (0, 0, 100, 30), msg);
	}
}
```

参考までにabstractの中身

```java:hoge.aar
package go.hoge;

import go.Seq;

public abstract class Hoge {
    private Hoge() {
    }

    public static void touch() {
    }

    private static native void _init();

    public static native String myFunction();

    static {
        Seq.touch();
        _init();
    }
}
```



## 参考

* [ゴルーチンと並行性パターン](http://qiita.com/hayajo/items/4cd75f87e35e60ae11a9)
* [Command cgo](https://godoc.org/github.com/gophersjp/go/src/cmd/cgo)


## 関連記事

* [GomobileからAARを作ってUnityで動かしてみた](http://qiita.com/otmb/items/da5df727aa30283c4278)
* [Gomobileで作ったAARをばらしてShared LibraryだけをUnityで動かしてみた
](http://qiita.com/otmb/items/e4bb761e4f75c0730095)
* [GomobileからShared libraryを出力してみた](http://qiita.com/otmb/items/6a59951267d384052b59)