声明:迁移自本人CSDN博客https://blog.csdn.net/u013365635

目的:通过形参在Java 和C之间传递数据,尤其是大块的媒体数据
优点:避免通过返回值返回一个巨大的数据块
声明:下文的大量操作作者是为了在一个目录下完成全部动作适配的,你大可以有更好的做法。文中涉及的目录参考者根据自己需要修改。重点是介绍一个完整可用的例子。
Step1:Java源码:

package com.testjni;
public class TestJNI
{
public native void tranferBytes(byte[] dataFromNative);
static
{
// 装入动态链接库
System.load("D:\\eclipseWebWorkSpace\\testest\\src\\com\\testjni\\libTestJNI_amd64.dll");
}
public static void main(String[] args)
{
TestJNI testJNI = new TestJNI();
// byte[] dataFromNative既是java传递给本地方法的参数,也是希望本地方法修改的参数
byte[] dataFromNative = new byte[10];
System.out.println("before-->dataFromNative=" + dataFromNative);
for (int i = 0; i < 10; i++)
{
System.out.print(dataFromNative[i] + " ");
}
System.out.println("\n----------");
testJNI.tranferBytes(dataFromNative);
System.out.println("after-->dataFromNative=" + dataFromNative);
for (int i = 0; i < 10; i++)
{
System.out.print(dataFromNative[i] + " ");
}
}
}

Step2:生成java类
javah -classpath D:\eclipseWebWorkSpace\testest\src com.testjni.TestJNI
Step3:生成jni头文件
javah -classpath D:\eclipseWebWorkSpace\testest\src com.testjni.TestJNI
生成的头文件如下。注意extern “C” {这个不能删除,否则C++的Name Mangling起作用运行时就无法找到自己写的函数了。

/* DO NOT EDIT THIS FILE - it is machine generated */
/*为了编译方便,把原本生成的#include <jni.h>改成了#include "jni.h"*/
#include "jni.h
/* Header for class com_testjni_TestJNI */
#ifndef _Included_com_testjni_TestJNI
#define _Included_com_testjni_TestJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_testjni_TestJNI
* Method: tranferBytes
* Signature: ([B)V
*/
JNIEXPORT void JNICALL Java_com_testjni_TestJNI_tranferBytes
(JNIEnv *, jobject, jbyteArray);
#ifdef __cplusplus
}
#endif
#endif

Step4:编写C++源文件

#include "com_testjni_TestJNI.h"
JNIEXPORT void JNICALL Java_com_testjni_TestJNI_tranferBytes(JNIEnv *jniEnv, jobject obj, jbyteArray dataFromNative)
{
jbyte* p = jniEnv->GetByteArrayElements(dataFromNative, NULL);
//这个地方就可以根据业务需要修改java传入的形参的值
for (int i = 0; i < 10; i++)
{
p[i] = i;
}
jniEnv->ReleaseByteArrayElements(dataFromNative, p, 0);
return;
}

此时你的目录大概长这个样子

很遗憾,此时执行
cl/LD D:\eclipseWebWorkSpace\testest\src\com\testjni\com_testjni_TestJNI.cpp -o D:\eclipseWebWorkSpace\testest\src\com\testjni\libTestJNI_amd64.dll
是编译不过的,你还需要以下2个头文件的支持:
C:\Program Files\Java\jdk1.8.0_144\include\jni.h和
C:\Program Files\Java\jdk1.8.0_144\include\win32\jni_md.h
Step5:把这2个头文件拷贝到当前目录D:\eclipseWebWorkSpace\testest\src\com\testjni
Step6:如果jdk是64位的,需要打开Visual Studio x64 Cross Tools Command Prompt而不是那个32位的。
然后执行cl /LD D:\eclipseWebWorkSpace\testest\src\com\testjni\com_testjni_TestJNI.cpp -o D:\eclipseWebWorkSpace\testest\src\com\testjni\libTestJNI_amd64.dll
好,现在你的目录大概长这样

当然了,以上除了libTestJNI_amd64.dll外,其他2个都是副产品,不是必须的,可以删除了。
此时再去跑跑java 代码,输出
before–>dataFromNative=[B@15db9742
0 0 0 0 0 0 0 0 0 0


after–>dataFromNative=[B@15db9742
0 1 2 3 4 5 6 7 8 9

JNI的第1种写法 及 JNI通过形参修改Java数据的更多相关文章

  1. JNI的第2种写法:本地方法注册

    声明:迁移自本人CSDN博客https://blog.csdn.net/u013365635 孔乙己说,茴香豆的茴有四种写法,今天谈谈JNI的第2种写法:本地方法注册. 这种写法的好处是不需要使用ja ...

  2. 实现JNI的另一种方法:使用RegisterNatives方法传递和使用Java自定义类 (转)

    原帖地址:http://blog.csdn.net/qiuxiaolong007/article/details/7860610 除了使用传统方法实现JNI外,也可以使用RegisterNatives ...

  3. Java JNI 编程进阶 实例+c++数据类型与jni数据类型转换

    原文:http://www.iteye.com/topic/295776 JNI一直以来都很少去关注,但却是我心中的一个结,最近这几天刚好手头有点时间,因此抽空看了一下这方面的东西,整理了一份文档,J ...

  4. JNI/NDK开发指南(一)—— JNI开发流程及HelloWorld

    转载请注明出处:http://blog.csdn.net/xyang81/article/details/41777471 JNI全称是Java Native Interface(Java本地接口)单 ...

  5. JNI/NDK开发指南(十)——JNI局部引用、全局引用和弱全局引用

    转自:http://blog.csdn.net/xyang81/article/details/44657385   这篇文章比较偏理论,详细介绍了在编写本地代码时三种引用的使用场景和注意事项.可能看 ...

  6. JNI/NDK开发指南(三)——JNI数据类型及与Java数据类型的映射关系

    转载请注明出处:http://blog.csdn.net/xyang81/article/details/42047899 当我们在调用一个Java native方法的时候.方法中的參数是怎样传递给C ...

  7. java设计模式之单例模式(几种写法及比较)

    概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建 ...

  8. javascript函数的几种写法集合

    1.常规写法 function fnName(){ console.log("常规写法"); } 2.匿名函数,函数保存到变量里 var myfn = function(){ co ...

  9. php插入式排序的两种写法。

    百度了下插入式排序,百度百科中php版本的插入式排序如下: function insert_sort($arr) { // 将$arr升序排列 $count = count($arr); for ($ ...

随机推荐

  1. 开源DDD设计模式框架YMNNetCoreFrameWork第五篇-Swagger增加权限认证

    配置文件services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Version = " ...

  2. Hibernate--起步

    1.配置对象 配置对象是你在任何 Hibernate 应用程序中创造的第一个 Hibernate 对象,并且经常只在应用程序初始化期间创造.它代表了 Hibernate 所需一个配置或属性文件.配置对 ...

  3. Python 中 configparser 配置文件的读写及封装,配置文件存放数据,方便修改

    1. 将程序中不常变化的数据放在配置文件中,有什么好处? 将配置统一放在一起,进行统一管理,方便维护,方便修改 配置文件将存放测试数据比如: Excel文件名. 日志名. 用例执行的结果. 实际结果和 ...

  4. 019-PHP创建目录函数

    <?php if (mkdir("myDir1", 0777)) //创建目录的函数 { print("目录创建成功"); //目录建立成功 } else ...

  5. css怎么让图片垂直左右居中?(外层div是浮动且按照百分比排列)

    一.原始的居中方法是把div换成table <div style="width: 500px; height: 200px; border: solid 1px red; text-a ...

  6. js原型链理解(4)-经典继承

    经典继承就是组合继承,就是组合构造函数和原型链的优点混合继承. 1.避免引用类型的属性初始化 2.避免相同方法的多次初始化 function Super(name){ this.ages = [100 ...

  7. 每天一点点之 taro 框架开发 - taro静态资源引入

    1.说明: taro中客园自由的引用静态资源,不需要安装任何的loader 引用样式文件 通过ES6的import引入 2.引用js文件 import { functionName } from '. ...

  8. EE将于5月30日在英国推出首个5G网络

    英国移动运营商 EE 宣布计划于周三在英国推出 5G,该网络将于 5 月 30 日开通,第一批 5G 手机可从今天开始预订.EE 最初的 5G 网络部署将集中在六个城市(伦敦,加的夫,爱丁堡,贝尔法斯 ...

  9. HDU 5464:Clarke and problem

    Clarke and problem  Accepts: 130  Submissions: 781  Time Limit: 2000/1000 MS (Java/Others)  Memory L ...

  10. HDU 1003:Max Sum

    Max Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Su ...