zoukankan      html  css  js  c++  java
  • JAVA本地调用(JNI java调用c)

    记录一下工作内容,对术语了解不多,暂且这样记着吧。

     java调用c

    一、写jni的步骤如下:

    1.创建java类,定义接口函数,使用native修饰;

    2.将java类编译成class;

    3.将class编译成*.h头文件;

    4.在c/c++中实现java定义的接口函数;

    5.将该c/c++的实现导出动态链接库;

    6.将动态链接库放到java的库路径;

    7.使用。

    二、应该注意的一些问题:

    1.注意该java类所在的包,包会影响导出的头文件的名称,还会影响到头文件的生成;代码中不要出现中文;

    2.使用javac将类编译成class文件,该文件会出现在java文件同一目录下;

    3.使用javah将class文件编译成头文件,这一步需要注意,如果该类在某个包下,需要在src路径下进行编译,最后给出例子。

    4.在c/c++中实现时注意java类型和c/c++类型间的转换,我遇到的是jstring转换成char*的问题。

    对于如下函数

    JNIEXPORT void JNICALL Java_com_bbwang_JniTest_printMsg
    (JNIEnv *env, jobject o, jstring str)

    {

    }

    如果是c实现,调用GetStringUTFChars时应该如下调用

      const char *cstr = (*env)->GetStringUTFChars (env, str, NULL);

    如果是c++实现,调用GetStringUTFChars时需要如下操作

      const char *cstr = env->GetStringUTFChars (str, NULL);

    5.build时指定导出dll,需要将%JAVA_HOME%\include和%JAVA_HOME%\include\win32包含到additional include directories;

    6.在java中使用时只需要java的接口定义文件和导出的dll,具体使用时需要LoadLibrary,dll放在java.library.path下;

    三、具体实现的例子

    1.先是java文件,我的文件在com.bbwang包下!:

    package com.bbwang;

    public class JniTest
    {
      public native void printMsg(String str);

      public native long add(int left, int right);

      public native long minus(int left, int right);
    } // class JniTest end

    2.编译

    找到src路径下

    javac com\bbwang\JniTest.java 编译出class

    javah com.bbwang.JniTest 编译出头文件,头文件在src目录下,名称是com_bbwang_JniTest.h,头文件内容贴出来:

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class com_bbwang_JniTest */

    #ifndef _Included_com_bbwang_JniTest
    #define _Included_com_bbwang_JniTest
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
    * Class: com_bbwang_JniTest
    * Method: printMsg
    * Signature: (Ljava/lang/String;)V
    */
    JNIEXPORT void JNICALL Java_com_bbwang_JniTest_printMsg
    (JNIEnv *, jobject, jstring);

    /*
    * Class: com_bbwang_JniTest
    * Method: add
    * Signature: (II)J
    */
    JNIEXPORT jlong JNICALL Java_com_bbwang_JniTest_add
    (JNIEnv *, jobject, jint, jint);

    /*
    * Class: com_bbwang_JniTest
    * Method: minues
    * Signature: (II)J
    */
    JNIEXPORT jlong JNICALL Java_com_bbwang_JniTest_minus
    (JNIEnv *, jobject, jint, jint);

    #ifdef __cplusplus
    }
    #endif
    #endif

    4.c实现

    #include <stdio.h>
    #include <stdlib.h>
    #include "com_bbwang_JniTest.h"


    /*
    * Class: com_bbwang_JniTest
    * Method: printMsg
    * Signature: (Ljava/lang/String;)V
    */
    JNIEXPORT void JNICALL Java_com_bbwang_JniTest_printMsg
    (JNIEnv *env, jobject o, jstring str)
    {
      const char *cstr = (*env)->GetStringUTFChars (env, str, NULL);
      fprintf (stdout, "from native method, msg = %s\n", cstr);
      (*env)->ReleaseStringUTFChars (env, str, cstr);
    }

    /*
    * Class: com_bbwang_JniTest
    * Method: add
    * Signature: (II)J
    */
    JNIEXPORT jlong JNICALL Java_com_bbwang_JniTest_add
    (JNIEnv *env, jobject o, jint left, jint right)
    {
      return left + right;
    }

    /*
    * Class: com_bbwang_JniTest
    * Method: minues
    * Signature: (II)J
    */
    JNIEXPORT jlong JNICALL Java_com_bbwang_JniTest_minus
    (JNIEnv *env, jobject o, jint left, jint right)
    {
      return left - right;
    }

    5.导出dll

    6.可以使用了

    我将dll放到了%JAVA_HOME%\bin目录下,调用的文件内容如下:

    package com.bbwang;

    public class ForTest
    {
      static

      {
        System.loadLibrary("JniTest");
      }

      public static void main(String[] args)
      {

        // 不知道java.library.path在哪就直接打出来撒
        // System.out.println(System.getProperty("java.library.path"));
        System.out.println("test start");
        JniTest jt = new JniTest();
        jt.printMsg("native method start");

        long result = jt.add(1,2);
        System.out.println(result);
        result = jt.minus(6,2);
        System.out.println(result);

        jt.printMsg("native method end");
      }
    } // class ForTest end

    7.恩,可以看到结果了:

    test start
    3
    4
    from native method, msg = native method start
    from native method, msg = native method end

    结果还是比较神奇的,消息竟然是最后打出来的

  • 相关阅读:
    [LeetCode] Sqrt(x)
    [LeetCode] Rotate Array
    【经典算法】贪心算法
    【经典算法——查找】二分查找
    ARP(Adress Resolution Protocol): 地址解析协议
    【经典算法】分治策略
    [LeetCode] Recover Binary Search Tree
    [LeetCode] Convert Sorted Array to Binary Search Tree
    python数据类型之字典(dict)和其常用方法
    简单了解hash
  • 原文地址:https://www.cnblogs.com/binbinjx/p/3288129.html
Copyright © 2011-2022 走看看