LoginSignup
3
3

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-09-15

今回は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の書き方からだいぶ変わるのでこの書き方で実装すべきかどうかという点

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() {
}
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

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

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

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

public class HogeClass {
    public static String get(){
        return Hoge.myFunction();
    }
}
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の中身

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();
    }
}

参考

関連記事

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3