JNI系列(二)Java代码通过JNI与C++代码通信

我们来看下一个简单的JNI示例,JAVA代码如下:

 

1)编写声明了native方法的Java类

 

public class JniHelloWord {

    /**
     * native关键字,表明这个方法使用java以外的语言实现,方法不包括实现,因为我们要用c/c++语言实现它
     */
    public native void printHelloWorld();

    static {
        //System.loadLibrary("hello")这句代码,它是在静态初始化块中定义的,系统用来装载hello库,
        //这就是我们在后面生成的hello.dll
        System.loadLibrary("hello");
    }

    public static void main(String[] args) {
        new JniHelloWord().printHelloWorld();
    }
}

2)将Java源代码编译成class字节码文件

 

在目录下执行:

javac -encoding UTF-8 JniHelloWord.java

 

3)用javah 命令生成.h头文件

 

在目录下执行:

javah JniHelloWord

会生成JniHelloWord.h头文件,就像java是运行main方法一样,javah就是提供具有native method的java对象的c函数接口,内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JniHelloWord */

#ifndef _Included_JniHelloWord
#define _Included_JniHelloWord
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     JniHelloWord
 * Method:    printHelloWorld
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_JniHelloWord_printHelloWorld
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

最重要的C函数接口就是这样:

JNIEXPORT void JNICALL Java_JniHelloWord_printHelloWorld(JNIEnv *, jobject);

JNIEXPORT :在Jni编程中所有本地语言实现Jni接口的方法前面都有一个"JNIEXPORT",这个可以看做是Jni的一个标志,是用于导出函数的、依赖于编译器的指示符。返回类型是映射到 Java 类型的 C/C++ 类型

void :这个学过编程的人都知道,当然是方法的返回值了。

JNICALL :这个可以理解为Jni 和Call两个部分,和起来的意思就是 Jni调用XXX(后面的XXX就是JAVA的方法名)。

Java_JniHelloWord_printHelloWorld:这个就是被上一步中被调用的部分,也就是Java中的native 方法名,这里起名字的方式比较特别,是:包名+类名+方法名。

JNIEnv * env:这个env可以看做是Jni接口本身的一个对象,jni.h头文件中存在着大量被封装好的函数,这些函数也是Jni编程中经常被使用到的,要想调用这些函数就需要使用JNIEnv这个对象。例如:env->GetObjectClass()。(详情请查看jni.h)

jobject obj:代表着native方法的调用者,本例即new JniHelloWord();但如果native是静态的,那就是JniHelloWord.class .

也就是说,我们的native printHelloWorld()方法实际上是运行C的Java_JniHelloWord_printHelloWorld()这个方法,我们是不能随意写C函数名的的,只能这样写。

 

关于jni.h头文件

 

它实际上就存在%JAVA_HOME%\include下面的一个文件,另外还有个%JAVA_HOME%\include\win32下的jni_md.h.

jni.h头文件主要定义了以下内容,图片来自网上:

 

4)用本地代码实现.h头文件中的函数

 

接下来我们可以照着接口去写真正的函数方法了.新建JniHelloWord.cpp,我这用的是Visual Studio 2019,步骤如下,新建一个项目,选择“动态链接库(DLL)”

 

复制3个文件到目录中

VS添加到头文件目录中


修改JniHelloWord.h 文件

#include <jni.h> 改为 #include "jni.h"

然后新建HellowWorld.cpp文件

输入如下代码:

// JniHelloWord.cpp : 定义 DLL 的导出函数。
//
#include "JniHelloWord.h"
#include "jni.h"    //注意添加这句

#include<iostream>


using namespace std;

JNIEXPORT void JNICALL Java_JniHelloWord_printHelloWorld(JNIEnv* env, jobject obj)
{
    cout << "Hello World!" << endl;
    cout << "I come from C++!" << endl;
}

 

5)将本地代码编译成动态库(windows:*.dll,linux/unix:*.so,mac os x:*.jnilib)

 

解决方案右击-》 配置管理器,

然后点击生成

6)复制这个dll文件,改名hello.dll  并放在项目路径下面

 

7)测试

 

在该项目下执行

java JniHelloWord

输出如下:

如果报错:

Can't load IA 32-bit .dll on a AMD 64-bit platform

在活动解决平台方案选择 x64

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值