JNI 如何使用dlopen,dlsym调用第三方自定义的 .so库( JNI->C,C++)

和前一篇 JNI->JNI唯一不同的就是 编译出.so 需要在Linux 上,然而直接用linux gcc 编译出的.so 是不能被NDK编译的会出 incompatible target 的错误所以需要用到交叉环境 即是 linux下的 ndk编译环境

我用的是 virtual box 装的 ubuntu 64虚拟机

第一步:制作第一个linux下的动态库来模拟第三方动态库

首先你的linux环境必须装有linux版本的NDK,现在我们来从NDK中分离出独立的工具链,这样我们在制作第三方动态库的时候就不用写makefile了。

在linux命令终端解压压缩包得android-ndk-xx然后再linux终端进入android-ndk-xx的根目录,$ build/tools/make-standalone-toolchain.sh --platform=<PLATFORM> --install-dir=<INSTALL_PATH>按上述格式输入下面的命令

$ build/tools/make-standalone-toolchain.sh --platform=android-14 --install-dir=/home/xx/toolchain/arm-linux-androideabi/

这条命令的意思就是将交叉编译工具完整复制出来,android-14是你的API ,-dir后面是你要复制安装到的目录,执行完后你会发现在/home/xxx/下发现你新建的toolchain目录,到这里我们已经从NDK中分离出独立的工具链了。最后为了方便我们需要设置一下环境变量,如果不设置,每次你都要这样写/home/xx/toolchain/arm-linux-androideabi/bin/arm-linux-androideabi-gcc -c Add.c 这样相当麻烦。

在Linux终端输入 $ sudo -s 获取超级权限,再输$gedit /etc/profile 在弹出的profile文件里将以下内容:export PATH=$PATH:/home/laijingquan/toolchain/arm-linux-androideabi/bin 加到文件的最后一行(这句什么意思?大神可以略去本人下面的赘述。简单说就是设置这个环境变量后,你后面执行arm-linux-androideabi-gcc这个命令时就会自动在:/home/laijingquan/toolchain/arm-linux-androideabi/bin这个目录里去寻找。)接着再执行 $ source /etc/profile 让环境变量立即生效。


arm-linux-androideabi-gcc -c xxxx.cpp 生成.o的文件

arm-linux-androideabi-gcc -shared -fPCI -o libxxxx.so xxxx.o  生成动态链接库.so文件

第二部:

         将生成的.so 文件 拷贝到 工程目录 jni下,在jni下新建 include文件夹将.h文件拷贝进去。

在 原始的C 语言.h文件里面加上3行代码:

第一行加 include<jni.h>  
在所有include 最下边加上 extern "C" { 
 就是包含你所有的接口名,将接口名最前面加上JNIEXPORT,中间加上 JNICALL ,就变成了这个摸样就行了:
 JNIEXPORT void JNICALL neuglClearColor(float r, float g, float b, float alpha);
}


还需要在 加载本地JNI库的地方加载下:

public class NativeInterface {
	
	public native static int init_view();
	public native static int draw_view();
	public native static void neuglClearColor(float r,float g,float b,float alpha);
	static{
		System.out.println("java start load MyTestLib.so....");
		System.loadLibrary("MyTestLib");
		System.out.println(System.mapLibraryName("MyTestLib"));
		System.out.println("java loaded MyTestLib.so");
		
		System.out.println("java start load Jtestc.so....");
		System.loadLibrary("Jtestc");         
		System.out.println("java loaded Jtestc.so");
	}
}


最后贴上 .mk文件代码:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := MyTestLib
LOCAL_SRC_FILES := eslib/libMyTestLib.so
LOCAL_C_INCLUDES := eslib/include
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := Jtestc
LOCAL_SRC_FILES := Jtestc.cpp
LOCAL_LDLIBS := -lGLESv2
LOCAL_LDLIBS += -llog -lz -lm
LOCAL_SHARED_LIBRARIES := MyTestLib
include $(BUILD_SHARED_LIBRARY)




你可能感兴趣的:(target,incompatible,dlsym,dlopen,调用原始的c,语言.so文件)