本地方法(JNI)——数值参数与返回值

来源:互联网 发布:美国大数据上市公司 编辑:程序博客网 时间:2024/05/16 06:11

【0】README

1) 本文部分文字描述 转自 core java volume 2 , 旨在理解 本地方法(JNI)——数值参数与返回值 的基础知识 ;
2) for source code, please visit https://github.com/pacosonTang/core-java-volume/tree/master/coreJavaAdvanced/chapter12/jni_numParamAndReturnValue


【1】本地方法(JNI)——数值参数与返回值的实现步骤

1)problem+solution:

  • 1.1)problem: 在一些平台上 C 语言中的 int 是 16位的,在另外一些平台上是 32 位的;而 java 平台上int 类型总是32位的;
  • 1.2) solution: java 本地接口定义了 jint, jlong 等类型;

2) 表 12-1 显示了 java 数据类型和 C 数据类型的对应关系:

  • 2.1) 在头文件jni.h 中: 这些类型被 typedef 语句声明为 在 目标平台上等价的类型。 该头文件还定义了常量 JNI_FALSE=0 , JNI_TRUE=1;

3) 用 printf 函数格式化数字

  • 3.1)看个荔枝: 以下代码使用本地方法来打印给定域宽度和精度的浮点数:
package com.corejava.chapter12_2;public class MyPrintf{    public static native int print(int width, int precision, double value);}
  • 3.2)注意: 用C实现该方法,所有的int 和 double 参数都要转换为 jint 和 jdouble;

    #include "Printf1.h"#include <stdio.h>JNIEXPORT jint JNICALL Java_Printf1_print(JNIEnv* env, jclass cl, jint width, jint precision, jdouble x) {     char fmt[30];   jint ret;   sprintf(fmt, "%%%d.%df", width, precision);   ret = printf(fmt, x);   fflush(stdout);   return ret;}

4) 用 printf 函数格式化数字的实际实现steps:

  • step1) 构建java类,用于定义本地方法; 并构建测试类,用于测试 java 调用本地方法是否成功;
    这里写图片描述
    Attention) 若 static 中的 代码改为:

static
{
System.load(“XX”);
}
那么 load 里面的文件应该使用 绝对路径而不是相对路径;(不然会抛出异常, for detailed spec , please visit http://javarevisited.blogspot.jp/2012/03/javalangunsatisfiedlinkerror-no-dll-in.html)
这里写图片描述

  • step2)编译MyPrintf, 并用javah 导出类的头文件 .h

    javac com/corejava/chapter12_2/MyPrintf.java
    javah com.corejava.chapter12_2.MyPrintf
    这里写图片描述

  • step3) copy com_corejava_chapter12_2_MyPrintf.h 里的 print函数原型到 新建的 MyPrintf.c 文件中, 并实现 print 函数, 如下所示:
    这里写图片描述

#include ""#include <stdio.h>JNIEXPORT jint JNICALL Java_com_corejava_chapter12_12_MyPrintf_print  (JNIEnv* env, jclass cl, jint width, jint precision, jdouble x){ char fmt[30];    jint ret;    sprintf(fmt, "%%%d.%df", width, precision);    ret = printf(fmt, x);    fflush(stdout);    return ret;}
  • step4) 编译该 c文件,并编译到动态装载库中:

    gcc -c -I /usr/java/jdk1.7/include/ -I /usr/java/jdk1.7/include/linux/ MyPrintf.c
    gcc -shared -fPIC -o libMyPrintf.so MyPrintf.o
    这里写图片描述

  • step5)编译并运行java 文件(MyPrintfTest.java)

    • step5.1)将该加载库 放入到 java.library.path 目录中:
      这里写图片描述

    • step5.2) 编译java文件并运行

      javac com/corejava/chapter12_2/MyPrintfTest.java
      java com.corejava.chapter12_2.MyPrintfTest
      这里写图片描述

0 0
原创粉丝点击