JNI调用
来源:互联网 发布:js脚本压缩 编辑:程序博客网 时间:2024/06/08 06:43
参考:http://www.cnblogs.com/bastard/archive/2012/05/19/2508913.html
http://blog.csdn.net/cghs123/article/details/7044826
1.新建Android工程 JNITest
static { //加载库文件 System.loadLibrary("HelloWorldJni"); }
声明c库中需要自定义的原生函数
private native String printJNI(String inputStr);HelloWorld整段代码如下:
package com.sirc.jni;import android.os.Bundle;import android.app.Activity;import android.util.Log;import android.view.Menu;public class HelloWorld extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String jniStr=printJNI("I am HelloWorld Activity"); Log.v("android", jniStr); } static { //加载库文件 System.loadLibrary("HelloWorldJni"); } //声明原生函数 参数为String类型 返回类型为String private native String printJNI(String inputStr);}
2.生成共享库的头文件
我们都知道在Eclipse中新建类后,eclipse会帮助我们在项目下自动建立去对应的class文件,位于项目目录下的\bin\classes中。共享库的头文件可以根据class文件通过javah编译生成。
通过命令进入项目根目录
再输入命令:javah -classpath bin\classes -d jni com.sirc.jni.HelloWorld
可以得到头文件com_sirc_jni_HelloWorld.h,位于跟目录/jni/下面
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_sirc_jni_HelloWorld */#ifndef _Included_com_sirc_jni_HelloWorld#define _Included_com_sirc_jni_HelloWorld#ifdef __cplusplusextern "C" {#endif/* * Class: com_sirc_jni_HelloWorld * Method: printJNI * Signature: (Ljava/lang/String;)Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_sirc_jni_HelloWorld_printJNI (JNIEnv *, jobject, jstring);#ifdef __cplusplus}#endif#endif
头文件中定义了与上层的访问接口Java_com_sirc_jni_HelloWorld_printJNI,方法名是按照”Java_包名_类名_方法名“来命名的。
3.实现JNI原生函数源文件
#include <jni.h>/* Native interface, it will be call in java code */JNIEXPORT jstring JNICALL Java_com_sirc_jni_HelloWorld_printJNI(JNIEnv *env, jobject obj, jstring inputStr) { // 从 instring 字符串取得指向字符串 UTF 编码的指针 const char *str = (const char *) (*env)->GetStringUTFChars(env, inputStr, JNI_FALSE); // 通知虚拟机本地代码不再需要通过 str 访问 Java 字符串。 (*env)->ReleaseStringUTFChars(env, inputStr, (const char *) str); return (*env)->NewStringUTF(env, "Hello World! I am Native interface");}/* This function will be call when the library first be load. * You can do some init in the libray. return which version jni it support. */jint JNI_OnLoad(JavaVM* vm, void* reserved) { void *venv; if ((*vm)->GetEnv(vm, (void**) &venv, JNI_VERSION_1_4) != JNI_OK) { return -1; } return JNI_VERSION_1_4;}
JNI_OnLoad函数JNI规范定义的,当共享库第一次被加载的时候会被回调。
Java_com_sirc_jni_HelloWorld_printJNI是头文件中方法的实现,可以通过这里获取上层传过来的参数,并在这里返回数据给上层框架使用。
注:这段代码是从其他网站上copy过来的,运行时如果出现错误stray '/241' in program ,该错误是指源程序中有非法字符,需要去掉非法字符。
解决方法:来源于http://blog.sina.com.cn/s/blog_6bc5571a0100zmft.html
(1)把所粘的文字放到记事本里就行了
(2)把出错行的空格删掉重新打一下试试。
4.编译生成so库
4.1在jni文件夹下面新建Android.mk文件,文件内容如下:
LOCAL_PATH:= $(call my-dir)# 一个完整模块编译include $(CLEAR_VARS)LOCAL_SRC_FILES:=com_sirc_jni_HelloWorld.cLOCAL_C_INCLUDES := $(JNI_H_INCLUDE)LOCAL_MODULE := libHelloWorldJniLOCAL_SHARED_LIBRARIES := libutilsLOCAL_PRELINK_MODULE := falseLOCAL_MODULE_TAGS :=optionalLOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -lloginclude $(BUILD_SHARED_LIBRARY)
系统变量解析:
LOCAL_PATH - 编译时的目录
$(call 目录,目录….) 目录引入操作符
如该目录下有个文件夹名称 src,则可以这样写 $(call src),那么就会得到 src 目录的完整路径
include $(CLEAR_VARS) -清除之前的一些系统变量
LOCAL_MODULE - 编译生成的目标对象
LOCAL_SRC_FILES - 编译的源文件
LOCAL_C_INCLUDES - 需要包含的头文件目录
LOCAL_SHARED_LIBRARIES - 链接时需要的外部库
LOCAL_PRELINK_MODULE - 是否需要prelink处理
include$(BUILD_SHARED_LIBRARY) - 指明要编译成动态库
4.2编译
我这里使用NDK来进行编译,首先要下载安装NDK。
Android NDK安装很简单,直接到http://developer.android.com/tools/sdk/ndk/index.html 下载android-ndk-r8e-windows-x86.zip 解压即可,接着设置环境变量。右击我的电脑属性,切换到高级选项卡,单击环境变量,在系统变量下单击编辑在Path变量名下直接变量值;D:\Android\android-ndk-r8e-windows-x86\android-ndk-r8e\ ,也就是你的解压路径,其中有个封号与前面的变量值分割。单击确定NDK就安装好了。
在命令行中使用ndk-build编译,过程如下
5.运行测试
运行JNITest项目,在logcat中查看运行结果。可以看到
上层打印情况:
- JNI调用
- JNI调用
- JNI调用
- JNI调用
- JNI调用
- jni 调用
- jni调用
- JNI调用
- jsp调用jni方法
- JNI调用的注意事项
- 使用jni调用unrar
- 通过JNI调用matlab
- java 调用dll JNI
- JNI 调用dll
- Mac Java Jni 调用
- Android JNI 调用
- JNI 调用C/C++
- JAVA-JNI调用GDAL
- 使用imageview显示Gif图片
- 12.1 剪贴板的简单用法
- JVM 堆栈区域数据存放流程
- Leetcode161: Repeated DNA Sequences
- shell 中数学计算总结
- JNI调用
- mmap详细解释
- Ubuntu开机报错:could not update ICEauthority file /home/lstanding/.ICEauthority 并且不能进入开机页面
- java入门--java连接SQLServer数据库
- 关于EMGU CV的那些事——1.环境搭建(win8 vs2012 emgucv3.0)
- c++封装多线程类
- QT在VS2010下的使用配置
- 10 款最好的远程桌面软件
- 1.mysql学习笔记:mysql的源码安装