Ⅰ. はじめに
AndroidはLinuxがベースのOSですが共有ライブラリをLinuxで利用する事が出来ません。
C言語ライブラリの実装が異なる為です。
OS | C言語ライブラリ |
Linux | glibc |
Android | Bionic libc |
Ⅱ. やり方
本記事のプロジェクトファイルはこちら
1. 共有ライブラリのサンプルプログラムを書く
#include <jni.h> extern "C" { JNIEXPORT jstring JNICALL Java_com_example_hellojni_MainActivity_helloworld(JNIEnv* env, jobject thiz) { return env->NewStringUTF("Hello World!"); } }
2. 1をコンパイルする
> ndk-build [armeabi-v7a] Compile++ thumb: helloworld <= main.cpp [armeabi-v7a] SharedLibrary : libhelloworld.so
3. 共有ライブラリを利用するサンプルプログラムを書く
import com.github.unidbg.linux.android.AndroidEmulatorBuilder; import com.github.unidbg.linux.android.AndroidResolver; import com.github.unidbg.linux.android.dvm.AbstractJni; import java.io.File; class NativeTest extends AbstractJni { public void callFunction(){ var emulator = AndroidEmulatorBuilder .for32Bit() .setProcessName("com.example.hellojni") .build(); var memory = emulator.getMemory(); memory.setLibraryResolver(new AndroidResolver(19)); var vm = emulator.createDalvikVM(null); vm.setJni(this); var library = vm.loadLibrary(new File("src/main/resources/libhelloworld.so"), false); library.callJNI_OnLoad(emulator); var result = vm .resolveClass("com/example/hellojni/MainActivity") // Java VM型のシグネチャ // https://docs.oracle.com/javase/jp/8/docs/technotes/guides/jni/spec/types.html .callStaticJniMethodObject(emulator, "helloworld()Ljava/lang/String;"); System.out.println(result.toString()); } } public class Main extends AbstractJni { public static void main(String[] args){ var nativeTest = new NativeTest(); nativeTest.callFunction(); } }
実行結果
Hello World!
FAQ
Q. unidbgはスレッドセーフですか?
A.いいえ
https://github.com/zhkl0228/unidbg/issues/181#issuecomment-689734652