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

【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
      这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值