jni 如何返回一个类给java

13 篇文章 0 订阅

之前用jni 技术一直是传输一些简单的数据结构,int float ,int[] float[] byte[] 这些简单的数据格式,但是如果数据比较多,一个返回值表示不完,需要调用多个函数返回,这样就导致程序接口复杂,如果程序加锁,还不能在一个函数里面完成,那该怎么处理呢,如果能像 c/c++ 一样返回一个结构体(也就是java中的类)那该多好啊,研究一段时间终于成功
struct info
{
int faceNum; // 数量
char * Base64CutImage; // Base64图片对应 java String
char * ByteCutImage; // 数组对应java byte[] ,长度不确定
}

https://blog.csdn.net/baidu_31872269/article/details/85055573
最好是参考上一篇是如何创建工程的

测试环境是win10 , eclipse java 工程,vs2015 生成dll
如果想在Android上用,此博客也适用
好吧,还是啰嗦一下吧
eclipse 创建一个工程JavaGetCstruct
在src下面创建一个包com.faceos.jni
在包下面创建三个类
InterfaceJNI.java // 接口类
ResultInfo.java // 返回的结构体类
test.java // 测试类

InterfaceJNI.java

package com.faceos.jni;

public class InterfaceJNI {
	public static native ResultInfo getResult(); // 静态接口类,返回值是一个类
	static{
		System.out.println("teststruct !");
		System.loadLibrary("teststruct");
	}
}

ResultInfo.java

package com.faceos.jni;

public class ResultInfo {
	
	private int faceNum;
	
	private String Base64CutImage;
	
	private byte[] byteCutImage;
	
	public int getfaceNum()
	{
		return faceNum;
	}
	public String getBase64CutImage()
	{
		return Base64CutImage;
	}
	public byte[] getByteCutImage()
	{
		return byteCutImage;
	}
	public ResultInfo(int faceNum_, String Base64CutImage_, byte[] byteCutImage_)
	{
		this.faceNum = faceNum_;
		this.Base64CutImage = Base64CutImage_;
		this.byteCutImage = byteCutImage_;
	}
}

test.java

package com.faceos.jni;

public class test {
	
	public static void main(String[] args) {
	
		ResultInfo resultInfo = InterfaceJNI.getResult();
		System.out.println("faceNum = " + resultInfo.getfaceNum());
		System.out.println("String = " + resultInfo.getBase64CutImage());
		System.out.println("byteCutImage = " + resultInfo.getByteCutImage().length);
		for(int i = 0; i < resultInfo.getByteCutImage().length; i ++)
		{
			System.out.println("a["+i + "] = " + resultInfo.getByteCutImage()[i]);
		}
	}
}

ok java工程创建完毕
vs 创建一个工程控制台程序teststruct,空项目

创建一个main.cpp
#include <stdio.h>

int main()
{
return 0;
}

javah 命令把InterfaceJNI.class 生产头文件
拷贝到工程目录下
创建一个InterfaceJNI.cpp


#include "com_faceos_jni_InterfaceJNI.h"

extern "C"
{

	JNIEXPORT jobject JNICALL Java_com_faceos_jni_InterfaceJNI_getResult
	(JNIEnv *env, jobject obj)
	{

		jclass jclassResultInfo = env->FindClass("com/faceos/jni/ResultInfo"); // 获取类 引用

		jmethodID jidResultInfo =
			env->GetMethodID(jclassResultInfo, "<init>", "(ILjava/lang/String;[B)V"); // 获取类的方法,此方法是构造函数

		// "(ILjava/lang/String;[B)V" 解释一下这个字符串,V代表返回空类型, ()号里面代表三个参数, 分解成三个分别是(我用空格隔开)   I   Ljava/lang/String;  [B   分别代表整数,字符string,和byte[] 自己体会

		int faceNum = 1;

		jstring jstr = env->NewStringUTF("hello world ");

		int mSize = 100;
		char buffer[100] = { 0 };
		for (int i = 0; i < mSize; i++)
		{
			buffer[i] = i;
		}
		jbyteArray byteA = env->NewByteArray(mSize);
		env->SetByteArrayRegion(byteA, 0, mSize, (const jbyte*)buffer);
		jobject result = env->NewObject(jclassResultInfo, jidResultInfo, faceNum, jstr, byteA); // 返回值不需要要释放
		env->DeleteLocalRef(byteA);  // 中间变量需要释放
		env->DeleteLocalRef(jstr); // 中间变量需要释放
		return result;
	}
}

好了,配置一个jni 路径,在jdk 下面
在属性下面设置生产动态库dll
编译就可生产dll

将dll 拷贝到eclispe 指定lib 路径下,或者把dll 所在路径配置到环境变量下面,执行eclipse 就可以啦

工程代码
https://download.csdn.net/download/baidu_31872269/10865531

代码更正,需要释放jmethodID, 所以把这个初始化时候存起来

#include "com_faceos_jni_InterfaceJNI.h"
JavaVM* vm_global;
jclass jclassResultInfo;
extern "C"
{
// 这个函数不用手动调用,加载库时候自动调用,如果不重载就不调用
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
		JNIEnv* env = nullptr;
		if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
			return -1;
		}


		vm_global = vm;

		jclass jclassResultInfo_temp = env->FindClass("com/faceos/jni/ResultInfo"); // 获取类 引用

		jclassResultInfo = (jclass)env->NewGlobalRef(jclassResultInfo_temp);

		

		LOGE("JNI_OnLoad ok .....");
		return JNI_VERSION_1_6;
	}
// 和上个函数相反
	JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved) {
		JNIEnv* env = nullptr;
		if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
			return;
		}
		env->DeleteGlobalRef(jclassResultInfo);


	}

	JNIEXPORT jobject JNICALL 
	Java_com_faceos_jni_InterfaceJNI_getResult
	(JNIEnv *env, jobject obj)
	{

	//	jclass jclassResultInfo = env->FindClass("com/faceos/jni/ResultInfo"); // 获取类 引用

		jmethodID jidResultInfo =
			env->GetMethodID(jclassResultInfo, "<init>", "(ILjava/lang/String;[B)V"); // 获取类的方法,此方法是构造函数

		// "(ILjava/lang/String;[B)V" 解释一下这个字符串,V代表返回空类型, ()号里面代表三个参数, 分解成三个分别是(我用空格隔开)   I   Ljava/lang/String;  [B   分别代表整数,字符string,和byte[] 自己体会

		int faceNum = 1;

		jstring jstr = env->NewStringUTF("hello world ");

		int mSize = 100;
		char buffer[100] = { 0 };
		for (int i = 0; i < mSize; i++)
		{
			buffer[i] = i;
		}
		jbyteArray byteA = env->NewByteArray(mSize);
		env->SetByteArrayRegion(byteA, 0, mSize, (const jbyte*)buffer);
		jobject result = env->NewObject(jclassResultInfo, jidResultInfo, faceNum, jstr, byteA); // 返回值不需要要释放
		env->DeleteLocalRef(byteA);  // 中间变量需要释放
		env->DeleteLocalRef(jstr); // 中间变量需要释放
		return result;
	}
}
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值