ページ

2016年8月26日金曜日

やっぱりJNI

一時期JNAに凝ってましたが、やっぱり何だかんだでJNIのほうが取り回しやすいなと感じている今日この頃。
なもんで、超簡単なサンプルを載せておきます。(転用は自己責任でお願いします。)


<C++>

#include "jnisample_JniSample.h"
#include <iostream>

class Sample {
public:
  Sample() {
    std::cout << "constructor" << std::endl;
  }
  ~Sample() {
    std::cout << "destructor" << std::endl;
  }
};

#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     jnisample_JniSample
 * Method:    open
 * Signature: (Ljava/lang/String;)J
 */
JNIEXPORT jlong JNICALL Java_jnisample_JniSample_open
  (JNIEnv *env, jobject obj, jstring jconf)
{
  const char *conf = env->GetStringUTFChars(jconf, 0);
  Sample *obj = new Sample();
  env->ReleaseStringUTFChars(jconf, conf);
  return (jlong)obj;
}

/*
 * Class:     jnisample_JniSample
 * Method:    close
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_jnisample_JniSample_close
  (JNIEnv *env, jobject obj, jlong jhandle)
{
  delete (Sample *)jhandle;
}

#ifdef __cplusplus
}
#endif


<Java>

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package jnisample;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 */
public class JniSample {
    
    private long handle;
    
    static {
        System.loadLibrary("native_sample");
    }
    
    public JniSample(String conf) {
        handle = open(conf);
    }
    
    public void close() {
        close(handle);
    }
    
    private native long open(String conf);
    private native void close(long handle);

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        JniSample obj = new JniSample("hoge");
        System.out.println("object created.");
        obj.close();
        System.out.println("program end.");
    }
    
}



Java側のコード書いたあとで、

>javah -classpath classes jnisample.JniSample

こんなするとネイティブライブラリのヘッダができますので、あとは中身の実装をするだけです。