package com.maxwin.dab.jni;
public class Lib {
public native void hello();
}
Java_com_maxwin_dab_jni_Lib_hello(JNIEnv* env, jobject thiz);
JAVA_
+ package name
+ class name
+ func name
public native void arg1(int a);
public native void arg2(int a, int b);
void Java_com_maxwin_dab_jni_Lib_arg1(
JNIEnv* env, jobject thiz, jint a);
void Java_com_maxwin_dab_jni_Lib_arg2(
JNIEnv* env, jobject thiz, jint a, jint b);
Java type | C type | sig |
---|---|---|
boolean | jboolean | Z |
byte | jbyte | B |
char | jchar | C |
short | jshort | S |
int | jint | I |
long | jlong | J |
sig 晚點解釋
Java type | C type | sig |
---|---|---|
float | jfloat | F |
double | jdouble | D |
Any Object | jobject | 見下 |
透過 Java Reflection
CallStatic<type>Method
Call<type>Method
SetStatic<type>Field
Set<type>Field
GetStatic<type>Field
Get<type>Field
package com.maxwin.tw;
class Yume {
}
jclass clz = env->FindClass("com/maxwin/tw/Yume");
jmethodID init = env->GetMethodID(clz, "<init>", "()V");
jobject yume = env->NewObject(clz, init);
// ...
env->DeleteLocalRef(yume);
env->DeleteLocalRef(clz);
new Yume();
package com.maxwin.tw;
class Yume {
int dreamCounts;
}
jfieldID dreamCountsField = env->GetFieldID(
clz, "dreamCounts", "I");
env->SetIntField(yume, dreamCountsField, 101);
package com.maxwin.tw;
class Yume {
int dream(int a, int b) { return a + b; }
}
jmethodID dreamMethod = env->GetMethodID(
clz, "dream", "(II)I");
jint dreams = env->CallIntMethod(yume, dreamMethod, 50, 51);
jfieldID GetFieldID(
jclass clazz, const char *name, const char *sig)
jmethodID GetMethodID(
jclass clazz, const char *name, const char *sig)
const char *sig
?, Signature?[ + type sig
byte -> B -> Array + B = [B
byte[];
"[B"
L + full class name + ;
String; // java.lang.String
"Ljava/lang/String;"
( + args sig + ) + return sig
void foo(int a, int b, int c) {}
"(III)V"
Java type | sig |
---|---|
void | V |
void foo() | ()V |
byte[] | [B |
java.lang.String | Ljava/lang/String; |
int example1(int a, int b) {/*...*/}
"(II)I"
void example2(String a[]) {/*...*/}
"([Ljava/lang/String;)V"
app/build.gradle
apply plugin: 'com.android.application'
android {
externalNativeBuild {
cmake {
path "src/main/jni4/CMakeLists.txt"
}
}
sourceSets {
main {
jniLibs.srcDirs = ['src/main/jni4/jniLibs']
}
}
flavorDimensions 'cpuArch'
productFlavors {
arm {
ndk {
abiFilter 'armeabi'
}
}
}
// ...
}
產生 libhello.so
cmake_minimum_required(VERSION 3.4.1)
add_library(
hello SHARED
hello-jni.c
)
# Include libraries needed for hello-jni lib
target_link_libraries(
hello
android
log
)
public class Lib {
static {
System.loadLibrary("hello");
}
}
cmake_minimum_required(VERSION 3.4.1)
find_library(
log-lib
log
)
include_directories(
inc
)
set(distribution_DIR ${CMAKE_SOURCE_DIR}/jniLibs/${ANDROID_ABI})
add_library(dabforex SHARED IMPORTED)
set_target_properties(dabforex PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/libdablibforexpartner.so)
add_library(dabforamaryllo SHARED IMPORTED)
set_target_properties(dabforamaryllo PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/libdabcontroller.so)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fexceptions")
# lib xxx .so
add_library(
dabcontrollerdemo SHARED
demoMain.cpp
Yume+LEB128.cpp
Yume+Decoder.cpp
Yume+TPEG.cpp
Yume+JavaCallback.cpp
Yume+JNIInit.cpp
YumeJNI+ObjectAccess.cpp
)
# Include libraries needed for hello-jni lib
target_link_libraries(
dabcontrollerdemo
dabforamaryllo
dabforex
android
${log-lib}
)
~/dab/app/src/main/jni4> tree
.
├── CMakeLists.txt
├── xxx.cpp
├── inc
│ └── API.h
└── jniLibs
└── armeabi
├── libdabcontroller.so
└── libdablibforexpartner.so
限制 cmake 最低版本為 3.4.1
cmake_minimum_required(VERSION 3.4.1)
確保有 log lib
log-lib=log
find_library(
log-lib
log
)
把 inc 加入到 header search path
include_directories(
inc
)
不同手機 cpu abi 不同
# distribution_DIR=${CMAKE_SOURCE_DIR}/jniLibs/${ANDROID_ABI}
set(distribution_DIR ${CMAKE_SOURCE_DIR}/jniLibs/${ANDROID_ABI})
add_library(dabforex SHARED IMPORTED)
set_target_properties(dabforex PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/libdablibforexpartner.so)
add_library(dabforamaryllo SHARED IMPORTED)
set_target_properties(dabforamaryllo PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/libdabcontroller.so)
package com.maxwin.dab.jni;
public class Lib {
static {
System.loadLibrary("dablibforexpartner");
System.loadLibrary("dabcontroller");
System.loadLibrary("dabcontrollerdemo");
}
}
object
相關類型會有產生 local ref
目前遇到的上限為 512
超過便會發生 JNI ERROR
// 需要在適當時機處理掉
env->DeleteLocalRef(ref);
基本型態以及
struct _jfieldID; /* opaque structure */
typedef struct _jfieldID* jfieldID; /* field IDs */
struct _jmethodID; /* opaque structure */
typedef struct _jmethodID* jmethodID; /* method IDs */
一樣要在適當時機釋放 ref
使用時機多為需要 長期/多次 使用
newRef = env->NewGlobalRef(ref);
env->DeleteGlobalRef(newRef);
vm->AttachCurrentThread(&env, NULL);
// ...
vm->DetachCurrentThread();
可以在這兩個時機點 準備/釋放 globol ref
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env;
if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) {
return JNI_ERR; // JNI version not supported.
}
ctx.vm = vm;
ctx.env = env;
return JNI_VERSION_1_6;
}
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved) {
}
沒有問題就不用回答