• 深入理解Android(2)——理解Android中的JNI(中)


    阳光小强参加了CSDN博客之星评选,如果你觉得阳光小强的博客对你有所帮助,为小强投上一票吧:http://vote.blog.csdn.net/blogstar2014/details?username=lxq_xsyu#content

    在上一篇中我们了解了Android中有关JNI的使用,其实JNI是很早就有的,不是在Android创造的新技术,是SUN为我们提供的一种Java和本地代码之间相互调用的方法,这一篇我们来建立一个普通的Java工程来具体看一下Java中如何调用C/C++代码。

    一、新建一个普通Java工程

    package com.csdn.test;
    
    /**
     * 阳光小强 http://blog.csdn.net/dawanganban
     * @author lixiaoqiang
     *
     */
    public class TestJNI {
    	
    	public native void saveHello();
    
    	public static void main(String[] args) {
    		TestJNI jni = new TestJNI();
    		jni.saveHello();
    	}
    }
    在TestJNI中我们声明了一个native方法。

    二、生成C/C++头文件

    SUN的JDK中已经为我们提供了一个生成对应C/C++头文件的工具(javah)

    lixiaoqiangdeMac-mini:bin lixiaoqiang$ whereis javah
    /usr/bin/javah
    lixiaoqiangdeMac-mini:bin lixiaoqiang$ 
    说明:我这里用的是max os系统,如果你是windows系统,在jdk目录下寻找。

    找到我们工程文件所在的目录,执行javah命令如下:

    lixiaoqiangdeMac-mini:bin lixiaoqiang$ pwd
    /Users/lixiaoqiang/Documents/AndroidWorkspace/TestJNI/bin
    lixiaoqiangdeMac-mini:bin lixiaoqiang$ javah com.csdn.test.TestJNI
    lixiaoqiangdeMac-mini:bin lixiaoqiang$ ls 
    com			com_csdn_test_TestJNI.h
    lixiaoqiangdeMac-mini:bin lixiaoqiang$ 
    可以看到为我们生成了一个com_csdn_test_TestJNI.h的头文件

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class com_csdn_test_TestJNI */
    
    #ifndef _Included_com_csdn_test_TestJNI
    #define _Included_com_csdn_test_TestJNI
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     com_csdn_test_TestJNI
     * Method:    saveHello
     * Signature: ()V
     */
    JNIEXPORT void JNICALL Java_com_csdn_test_TestJNI_saveHello
      (JNIEnv *, jobject);
    
    #ifdef __cplusplus
    }
    #endif
    #endif

    三、生成动态库文件

    下面我们打开C/C++编辑器(我这里使用的时Xcode,在Windows平台上的朋友可以使用VisualStudio)

    main.cpp中我们输出一行文字,如下:

    #include "com_csdn_test_TestJNI.h"
    #include <iostream>
    using namespace std;
    
    JNIEXPORT void JNICALL Java_com_csdn_test_TestJNI_saveHello(JNIEnv * evn, jobject obj){
        cout << "hello world" << endl;
    }
    在编译的过程中会发现找不到jni.h和jni_md.h文件,这两个文件可以在JDK的include目录下找到,拷贝到工程中,下面将上面的工程导出动态链接库。

    在导出链接库(编译)的时候在MacOS下和在Linux, Windows有所不同, 不是编译成.so或者dll, 而是MacOS自己的jnilib. 并且jni.h的目录也比较特殊, 是/System/Library/Frameworks/JavaVM.framework/Headers/, 这个需要稍微注意一下, 具体的命令如下:

    lixiaoqiangdeMac-mini:TestJNI lixiaoqiang$ g++ -dynamiclib -o libhelloworld.jnilib main.cpp -framework JavaVM -I/System/Library/Frameworks/JavaVM.framework/Headers
    lixiaoqiangdeMac-mini:TestJNI lixiaoqiang$ ls
    com_csdn_test_TestJNI.h	jni_md.h		main.cpp
    jni.h			libhelloworld.jnilib
    lixiaoqiangdeMac-mini:TestJNI lixiaoqiang$ 
    可以看到在该目录生成了一个libhelloworld.jnilib文件,我们将该文件拷贝到我们Java工程的bin目录下(windows下是classes目录)

    向Java工程中添加加装动态库的代码(下面的static语句块中的System.loadLibrary方法)

    package com.csdn.test;
    
    /**
     * 阳光小强 http://blog.csdn.net/dawanganban
     * @author lixiaoqiang
     *
     */
    public class TestJNI {
    	
    	public native void saveHello();
    
    	public static void main(String[] args) {
    		TestJNI jni = new TestJNI();
    		jni.saveHello();
    	}
    	
    	static{
    		System.loadLibrary("helloworld");
    	}
    }
    最后将该库文件添加到Java程序可以访问的环境变量中就可以运行输出“helloworld"了。

    下一篇文章我们将来看一下如何在C/C++中调用Java中的方法

  • 相关阅读:
    性能篇系列—stream详解
    Java正则表达式详细解析
    干货系列性能篇之——序列化
    面试官之问:知道你的接口“QPS”是多少吗?
    Java性能之优化RPC网络通信
    Spring之 JDBC 异常
    Java性能之synchronized锁的优化
    浅谈Java中switch分支语句
    Spring Boot 之异步执行方法
    Java性能 -- Lock优化
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6468576.html
Copyright © 2020-2023  润新知