栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

JAVA通过JNI调用C++

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JAVA通过JNI调用C++

JAVA通过JNI调用C++ 0.前置条件与JNI预备知识

需要gcc编译器

字符javac++/c
Vvoidvoid
Zjbooleanboolean
Ijintint
Jjlonglong
Djdoubledouble
Fjfloatfloat
Bjbytebyte
Cjcharchar
Sjshortshort
[IjintArray[]int[]
[FjfloatArray[]float[]
[BjbyteArraybyte[]
[CjcharArraychar[]
[SjshortArrayshort[]
[DjdoubleArraydouble[]
[JjloneArraylong[]
[ZjbooleanArrayboolean[]
Ljava/lang/Stringjstring
其他对象类推
(Ljava/lang/String;I)Ljava/lang/String;  <===>  String helloJNI(String a,int b)
(II)V <===> void helloJNI(int a,int b)
1.创建Java项目 代码如下
public class JNITest {

    public native String helloJNI(String name,int age);

    public static void main(String[] args) {
        JNITest jniTest = new JNITest();
        String z3 = jniTest.helloJNI("z3", 18);
        System.out.println(z3);
    }
}

关于上述代码解释如下:native表示该函数的实现不是用java实现的,可能是C/C++等语言实现,

2.编写C++实现 2.1 创建JNI.cpp文件
// “jni.h” 由先从当前目录去找jni.h
#include "jni.h"

jstring cppJNI(JNIEnv* env, jobject clazz, jstring name, jint age) {
	const char* chars = "hello java";
	const jstring result = env->NewStringUTF(chars);
	const char* nameChar = env->GetStringUTFChars(name, NULL);
	return result;
}


JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
	JNIEnv* env;
	if (JNI_OK != vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_8)) {
		printf("JNI_OnLoad cloud not get jni env");
		return JNI_ERR;
	}
	jclass clazz = env->FindClass("com/huf/JNITest");

	//通过 JNINativeMethod映射 c++函数与java函数直接的关系,从而不用在C++ 提供的JNI函数时的函数名不需要按照一定规则才能访问
	JNINativeMethod methods[] = {
		{"helloJNI","(Ljava/lang/String;I)Ljava/lang/String;",(void*)cppJNI},
	};

	if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof((methods)[0])) < 0) {
		return JNI_ERR;
	}
	return JNI_VERSION_1_8;
}
2.2 将jdk环境下的 jni.h与jni_md.h复制到出来

<你的目录>jdk8u322-b06includejni.h

<你的目录>jdk8u322-b06includewin32jni_md.h

2.3 生成动态链接库

此步骤需要gcc编译器没有请自行安装

windowslinuxmac
dllsojnilib
gcc -shared -o JNITest.dll .JNI.cpp

执行成功会看见JNITest.dll文件

2.4 修改java代码
public class JNITest {

    static {
        System.loadLibrary("JNITest");
    }

    public native String helloJNI(String name,int age);

    public static void main(String[] args) {
        JNITest jniTest = new JNITest();
        String z3 = jniTest.helloJNI("z3", 18);
        System.out.println(z3);
    }
}

2.5 执行java main函数测试

不出意外会出现如下错误:

no JNITest in java.library.path

因为它默认会去默认的路径找这个JNITest.dll库,所以我们需要手动指定

-Djava.library.path=E:ideajnisrccomhuf

2.6 再次执行
hello java
2.7 C++回调java
  • c++代码如下
// pch.cpp: 与预编译标头对应的源文件
#include "jni.h"

JNIEnv* m_ENV = NULL;
JavaVM* m_JVM = NULL;
jobject object = NULL;

void callJava(const char* chars, int age) {
	bool flag = false;
	if (m_JVM->AttachCurrentThread((void**)&m_ENV, NULL) != JNI_OK) {
		fprintf(stderr, "AttachCurrentThread errorn");
		return;
	}
	flag = true;
	jclass clazz = m_ENV->GetObjectClass(object);
	//jclass clazz = m_env->FindClass("com/huf/JNITest");
	if (clazz == NULL) {
		fprintf(stderr, "GetObjectClass errorn");
		if (flag) {
			m_JVM->DetachCurrentThread();
		}
		return;
	}
	jmethodID method = m_ENV->GetMethodID(clazz, "callBack", "(Ljava/lang/String;I)V");
	if (NULL == method) {
		if (flag) {
			m_JVM->DetachCurrentThread();
		}
		fprintf(stderr, "GetMethodID errorn");
		return;
	}
	jobject object = m_ENV->AllocObject(clazz);
	jstring re = m_ENV->NewStringUTF(chars);
	m_ENV->CallVoidMethod(object, method, re, age);
	if (flag) {
		m_JVM->DetachCurrentThread();
	}
}

jstring cppJNI(JNIEnv* env, jobject clazz, jstring name, jint age) {
	const char* chars = "hello java";
	const jstring result = env->NewStringUTF(chars);
	const char* nameChar = env->GetStringUTFChars(name, NULL);
	object = clazz;
	callJava(nameChar, age);
	return result;
}


JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
	JNIEnv* env;
	if (JNI_OK != vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_8)) {
		printf("JNI_OnLoad cloud not get jni env");
		return JNI_ERR;
	}
	m_ENV = env;
	m_JVM = vm;
	jclass clazz = env->FindClass("com/huf/JNITest");

	//通过 JNINativeMethod映射 c++函数与java函数直接的关系,从而不用在C++ 提供的JNI函数时的函数名不需要按照一定规则才能访问
	JNINativeMethod methods[] = {
		{"helloJNI","(Ljava/lang/String;I)Ljava/lang/String;",(void*)cppJNI},
	};

	if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof((methods)[0])) < 0) {
		return JNI_ERR;
	}
	return JNI_VERSION_1_8;
}
  • java代码如下:
public class JNITest {

    static {
        System.loadLibrary("JNITest");
    }

    public native String helloJNI(String name,int age);

    public void callBack(String name, int age) {
        System.out.println("c++ ======> java");
        System.out.printf("name : %s n age : %d n", name, age);
    }

    public static void main(String[] args) {
        JNITest jniTest = new JNITest();
        String z3 = jniTest.helloJNI("z3", 18);
        System.out.println(z3);
    }
}

最后

可以将无用文件删除只留下如图

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/835261.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号