The discretion of a man deferreth his anger

; and it is his glory to pass over a transgression (Prov. 19:11 KJV) - このブログは基本的に画像処理やRTMなど技術に関することを書き連ねていきます。

Android NDKでネイティブ開発。

をしようとして割と手こずってるYAGです。
どうしても、画像処理とか、信号処理的な何かを入れようとすると、AndoridのJavaからだと何か遅いんですよね…。Android 2.Xになって、JITコンパイラがちゃんと作動する様なんで、それを通していればそこそこ早くなるらしいですが、カメラ→画像処理→出力みたいな事をやろうとすると途端にめんどっちくなる様です。ぁぁ…。Javaの馬鹿…orz<Javaは信号処理系に弱いと昔から思ってる訳ですけど…

という事で、Nativeです。C++です。と言っても、ANSI Cガリガリでは書けないので、JNIのC(サブセット)です。自分あんまりJNI使ったこと無いんですよね…(汗
Android NDKは今回は最新版のr5を使用。
http://developer.android.com/sdk/ndk/index.html
インストールやサンプルソースの動かし方はこちらのブログを参考に(thx!)
http://techbooster.jpn.org/environment/824/
もろもろ上手く行くと、10倍速位になるらしい。
http://labs.techfirm.co.jp/android/iguchi/1782
凄いワクテカ
さて、いざ組み込んでみよう…とすると、途端に分からないことがたくさん。特にBitmap周りをどう渡すんだ?という事に。一応、サンプルプログラムのBitmapPlasmaというのがあったので、それを参考にしてみるも、どこでデータの受け渡しをしてるのかさっぱり(汗(一応、*void pixelを通して、データ弄りやってるようなんですけどね…returnはどっから…?というのが…)
まぁ、いきなり大技を狙うより、小技を狙って行きましょうということで、試しに『本当に自分でNative実装含むプロジェクトを作って動くのかTrial』をやってみることに。

JniTest.java

package com.yagu1.JniTest;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Bitmap;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;

public class JniTest extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new JniView(this));
    }

    /* load our native library */
    static {
        System.loadLibrary("jni-view");
    }
}

class JniView extends View{

    private long testcalc;

    private long mStartTime;

    /* implementend by libplasma.so */
    private static native long timeval(long input, long time_ms);

	public JniView(Context context) {
		super(context);
		// TODO 自動生成されたコンストラクター・スタブ
        mStartTime = System.currentTimeMillis();

	}

	@Override protected void onDraw(Canvas canvas) {

		Paint jniPaint = new Paint();
		jniPaint.setStyle(Paint.Style.FILL);
		jniPaint.setARGB(255, 255, 255, 100);

        testcalc = timeval(testcalc, System.currentTimeMillis() - mStartTime);

        canvas.drawText(String.valueOf(testcalc), 50, 50, jniPaint);
        invalidate();
	}
}

jni-view.c

#include <string.h>
#include <jni.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

/* This is a trivial JNI example where we use a native method
 * to return a new VM String. See the corresponding Java source
 * file located at:
 *
 *   apps/samples/hello-jni/project/src/com/example/HelloJni/HelloJni.java
 */
JNIEXPORT jlong JNICALL Java_com_yagu1_JniTest_JniView_timeval( JNIEnv* env, jobject this, jlong  input, jlong  time_ms)
{
    return time_ms;

}

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := jni-view
LOCAL_SRC_FILES := jni-view.c

include $(BUILD_SHARED_LIBRARY)

色々と迷走してます(汗<Bitmapとか使いたかったんだけどどうやっていいかわからんし。
一応、何とか動いてるようです。ただ…JNIEXPORTとJNICALLが良く分からん><
自分もJavaあんまり分からんくなってきたなぁ…もう一回勉強しなおしかなぁ。