GradleでJNIを試す

GradleでJNIを試したときのメモ。

ソースコード

% tree .
.
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
    ├── hello
    │   └── c
    │       ├── com_example_HelloJNI.h
    │       └── hello.c
    └── main
        └── java
            └── com
                └── example
                    ├── HelloJNI.java
                    └── Main.java

build.gradle

MacOSの設定を追加。Windowsなどの設定も入れる場合はこちらを参照。

import org.gradle.internal.jvm.Jvm

plugins {
    id 'java'
    id 'application'
    id 'c'
}

group 'com.example'
version '1.0-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_11

repositories {
    mavenCentral()
}

model {
    components {
        hello(NativeLibrarySpec) {
            binaries.all {
                cCompiler.args '-I', "${Jvm.current().javaHome}/include"
                cCompiler.args '-I', "${Jvm.current().javaHome}/include/darwin"
            }
        }
    }
}

build.dependsOn 'helloSharedLibrary'

mainClassName = 'com.example.Main'

run {
    systemProperty 'java.library.path', file("${buildDir}/libs/hello/shared").absolutePath
}

src/hello/c

com_example_HelloJNI.h

HelloJNI.javaを作成後、ヘッダーファイルを自動生成する。

% javac -h -jni HelloJNI.java
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_HelloJNI */

#ifndef _Included_com_example_HelloJNI
#define _Included_com_example_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_HelloJNI
 * Method:    hello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_example_HelloJNI_hello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

hello.c

#include "com_example_HelloJNI.h"

JNIEXPORT void JNICALL Java_com_example_HelloJNI_hello(JNIEnv *env, jobject obj) {
  printf("Hello!\n");
}

src/main/java

HelloJNI.java

package com.example;

public class HelloJNI {
    static {
        System.loadLibrary("hello");
    }

    public native void hello();
}

Main.java

package com.example;

public final class Main {

    public static void main(String[] args) {
        HelloJNI jni = new HelloJNI();
        jni.hello();
    }
}

動作確認

% ./gradlew run 

> Task :run
Hello!

参考